/* ====================================================================
 * The UncleGED Open Source Software License
 *
 * Copyright (c) 1999-2003 D. M. DeBacker. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. Products derived from this software may not be called "UncleGED",
 *    nor may "UncleGED" appear in their name, without prior written
 *    permission of D. M. DeBacker.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL D. M. DEBACKER BE LIABLE FOR ANY 
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 */

using System;
using System.Collections;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace UGed
{
   #region Event Handler
   delegate void StatusMessageEventHandler(object sender, StatusMessageArgs e);

   class StatusMessageArgs : EventArgs
   {
      public string Message;
      public long CountTotal;
      public long Counter;
      public bool IsProgress;

      public StatusMessageArgs(string msg, long cntTotal, long counter, bool isProgress)
      {
         Message = msg;
         CountTotal = cntTotal;
         Counter = counter;
         IsProgress = isProgress;
      }
   }
   #endregion

   class GedReader
   {
      #region events
      public event StatusMessageEventHandler StatusMessage;

      private void FireStatusMessage(string message)
      {
         if (StatusMessage != null)
         {
            StatusMessageArgs e = new StatusMessageArgs(message, 0, 0, false);
            StatusMessage(this, e);
         }
      }

      private void FireProgressMessage(string message, long cntTotal, long counter)
      {
         if (StatusMessage != null)
         {
            StatusMessageArgs e = new StatusMessageArgs(message, cntTotal, counter, true);
            StatusMessage(this, e);
         }
      }
      #endregion


      #region local variables

      private bool _didCancel;

      public bool Cancel
      {
         set { _didCancel = value; }
      }


      private string _sFile;
      private bool _bStart;
      private StringFuncs sf = new StringFuncs();
      private string _srcTarget = "_self";

      public Individuals MyIndividuals;
      public Children MyChildren;
      public Families MyFamilies;
      public Sources MySources;
      public Notes MyNotes;
      public Surnames MySurnames;
      public Gendices MyGendices;
      public FileInfo MyFileInfo;
      public TimeLineEntries MyTimeLineEntries;
      public Locations MyLocations;
      public Occupations MyOccupations;
      public GedcomLines myGedcomFile;
      public IndiLines myIndiLines;

      private UGedProject m_cfg;
      private LocalApplication localSettings;

      private const short GET_DRIVE = 0;
      private const short GET_DIRECTORY = 1;
      private const short GET_FILENAME = 2;
      private const short GET_EXTENSION = 3;


      private const string Privacy = "[private]";

      private enum RecordTypes
      {
         rtHEAD = 0,
         rtINDI,
         rtFAM,
         rtNOTE,
         rtSOUR,
         rtOBJE,
         rtREPO,
         rtSUBN,
         rtSUBM,
      };

      #endregion

      /// <summary>
      /// Class constructor
      /// </summary>
      /// <param name=ConfigSettings></param>
      /// <param name=LocalSettings></param>
      /// <param name=FileName></param>
      /// 		
      public GedReader(UGedProject ConfigSettings, LocalApplication LocalSettings, string FileName)
      {
         localSettings = LocalSettings;
         m_cfg = ConfigSettings;
         _sFile = FileName;
      }

      #region public methods for processing gedcom
      /// <summary>
      /// called by main to read and process the gedcom file
      /// </summary>
      /// <param name=sTheFile></param>
      /// <param name=bFullProcess></param>
      /// 		
      public bool ProcessGedComFile(string sTheFile, bool bFullProcess)
      {
         string sFile;
         long NumBytes = 0;
         long BytesRead = 0;

         _didCancel = false;

         MyIndividuals = new Individuals();
         MyChildren = new Children();
         MyFamilies = new Families();
         MySources = new Sources();
         MyNotes = new Notes();
         MySurnames = new Surnames();
         MyFileInfo = new FileInfo();
         MyTimeLineEntries = new TimeLineEntries();
         MyLocations = new Locations();
         MyOccupations = new Occupations();
         myGedcomFile = new GedcomLines();
         myIndiLines = new IndiLines();


         sFile = sTheFile;
         _sFile = GetFilePart(sTheFile, GET_FILENAME) + GetFilePart(sTheFile, GET_EXTENSION);


         m_cfg.FileSource = _sFile;

         FireStatusMessage("Reading " + sFile + "...");
         FileStream fs;
         StreamReader sr;
         try
         {
            fs = new FileStream(sFile, FileMode.Open, FileAccess.Read);
            sr = new StreamReader(fs);
            NumBytes = fs.Length;
            FireStatusMessage("The file size is: " + NumBytes.ToString() + " bytes");
         }
         catch (Exception ex)
         {
            FireStatusMessage("Error in ProcessGedComFile : " + ex.Message);
            return false;
         }

         //read a line from the gedcom file
         string a;

         try
         {
            while ((a = sr.ReadLine()) != null)
            {
               if (_didCancel)
               {
                  goto CLEAN_UP;
               }
               if (a.Trim().Length != 0)
               {
                  ProcessGedData(a);  //process each line
               }
               BytesRead = BytesRead + a.Length;
               FireProgressMessage(String.Format("Processed {0} out of {1} bytes...", BytesRead, NumBytes), NumBytes, BytesRead);
            }
         }
         catch (Exception ex)
         {
            FireStatusMessage("Error while reading GEDCOM file: " + ex.Message);
            return false;
         }

         sr.Close();

         if (bFullProcess == true)
         {
            FireStatusMessage("Marking missing spouses...");
            FixFamiliesEach(); //if the husband or wife is an empty string change this to a question mark;
         }

         FireStatusMessage("File process complete!");

         if (_didCancel)
         {
            goto CLEAN_UP;
         }
         if (m_cfg.Privacy)
         {
            FireStatusMessage("Flagging private records...");
            MarkAsPrivate();
         }

         if (_didCancel)
         {
            goto CLEAN_UP;
         }

         _bStart = true;
         _didCancel = false;

         return true;

      CLEAN_UP:
         _sFile = "";
         _didCancel = false;
         MyIndividuals = null;
         MyChildren = null;
         MyFamilies = null;
         MySources = null;
         MyNotes = null;
         MySurnames = null;
         _bStart = true;

         return true;
      }
      #endregion

      #region private methods for processing gedcom
      //locals used by ProcessGedData
      private LifeEvent.EventTypes EventType;
      private RecordTypes RecType;
      private string _xrefid;
      private string _prevtag;
      private string _prevsrcid;
      private string _tag2;
      private string _tag1;
      private int _currevent;
      private string _filesrc;
      private string _taglevel1;
      private bool _isevent;

      /// <summary>
      /// Called by ProcessGedComFile
      /// </summary>
      /// <param name=sGedLine></param>
      /// 		
      private void ProcessGedData(string sGedLine)
      {
         //string errMsg = "";

         if (sGedLine.Trim().Length == 0) return;

         int iLevel;
         string sTag;
         string sData;
         string sTempData;
         int iSpaceOne;
         int posDelim;
         int iLineNumber;

         Individual TheIndividual;
         Child TheChild;
         Family TheFamily;
         Source TheSource;
         Note TheNote;
         LifeEvent NewEvent;
         DateTime dtTempDate;

         const string SLASH = "/";

         if (_bStart)
         {
            EventType = LifeEvent.EventTypes.etUnknown;
            RecType = RecordTypes.rtHEAD;
            _xrefid = "";
            _prevtag = "";
            _bStart = false;
         }

         iLineNumber = myGedcomFile.Add(sGedLine);
         iLevel = System.Convert.ToInt32(sf.Left(sGedLine, 1));
         iSpaceOne = sf.InStr(3, sGedLine, " ");
         if (iSpaceOne != 0)
         {
            sTag = sf.Trim(sf.Mid(sGedLine, 3, iSpaceOne - 2));
            sData = sf.Right(sGedLine, sf.Len(sGedLine) - iSpaceOne);
            sData = sf.Trim(sData);
         }
         else if (sf.Trim(sGedLine) != "")
         {
            sTag = sf.Trim(sf.Right(sGedLine, sf.Len(sGedLine) - 2));
            sData = "";
         }
         else
         {
            sTag = "";
            sData = "";
         }

         if (iLevel == 2)
         {
            _tag2 = sTag;
         }
         else if (iLevel < 2)
         {
            _tag2 = "";
         }

         if (iLevel == 1)
         {
            _tag1 = sTag;
         }
         else if (iLevel < 1)
         {
            _tag1 = "";
         }

         if (iLevel == 0)
         {
            _xrefid = sTag;
            sTag = sData;
            sData = "";
            _isevent = false;
            switch (sTag)
            {
               case "HEAD":
                  RecType = RecordTypes.rtHEAD;
                  break;
               case "INDI":
                  TheIndividual = new Individual();
                  TheIndividual.ID = _xrefid;
                  TheIndividual.LineNumber = iLineNumber;
                  myIndiLines.Add(_xrefid, iLineNumber);
                  MyIndividuals.Add(TheIndividual);
                  RecType = RecordTypes.rtINDI;
                  _currevent = 0;
                  break;
               case "FAM":
                  TheFamily = new Family();
                  TheFamily.ID = _xrefid;
                  MyFamilies.Add(TheFamily);
                  RecType = RecordTypes.rtFAM;
                  _currevent = 0;
                  break;
               case "NOTE":
                  TheNote = new Note();
                  TheNote.ID = _xrefid;
                  MyNotes.Add(TheNote);
                  RecType = RecordTypes.rtNOTE;
                  _currevent = 0;
                  break;
               case "SOUR":
                  TheSource = new Source();
                  TheSource.ID = _xrefid;
                  MySources.Add(TheSource);
                  RecType = RecordTypes.rtSOUR;
                  _currevent = 0;
                  break;
               case "OBJE":
                  //not used
                  RecType = RecordTypes.rtOBJE;
                  _currevent = 0;
                  break;
               case "REPO":
                  //not used
                  RecType = RecordTypes.rtREPO;
                  _currevent = 0;
                  break;
               case "SUBN": //???????
                  //not used
                  RecType = RecordTypes.rtSUBN;
                  _currevent = 0;
                  break;
               case "SUBM":
                  RecType = RecordTypes.rtSUBM;
                  _currevent = 0;
                  break;
            }
         }
         else
         {
            if (iLevel == 1)
            {
               _taglevel1 = sTag;
               _isevent = false;
            }
            switch (sTag)
            {
               case "_DETS":
                  EventType = LifeEvent.EventTypes.etDeathOfSpouse;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Death of Spouse";
                  MyFamilies[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "_MILT":
                  EventType = LifeEvent.EventTypes.etMilitary;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Military Service";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "_UNKN":
                  EventType = LifeEvent.EventTypes.etUnknown;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "";
                  NewEvent.EventDescription = sData;
                  switch (RecType)
                  {
                     case RecordTypes.rtINDI:
                        MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                        _isevent = true;
                        break;
                     case RecordTypes.rtFAM:
                        MyFamilies[_xrefid].LifeEvents.Add(NewEvent);
                        _isevent = true;
                        break;
                  }
                  break;
               case "_UID":
                  if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].PafUniqueID = sData;
                  break;
               case "ADDR":
                  if (iLevel == 1)
                  {
                     if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].Address = sData;
                  }
                  break;
               case "ADOP":
                  //adoption in child record
                  //need special handling for this
                  break;
               case "ALIA":
                  MyIndividuals[_xrefid].AliasName = sData;
                  break;
               case "_AKA": //PAF uses this. why not use ALIA?;
                  MyIndividuals[_xrefid].AliasName = sData;
                  break;
               case "AUTH":
                  if (RecType == RecordTypes.rtSOUR)
                  {
                     MySources[_xrefid].Author = sData;
                  }
                  break;
               case "BIRT":
                  EventType = LifeEvent.EventTypes.etBirth;

                  //added in 0.7 (not in vb version)
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Birth";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "BURI":
                  //EventType = etBurial
                  EventType = LifeEvent.EventTypes.etBurial;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Burial";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "CALN":
                  //the source call record
                  //I don't use this
                  break;
               case "CHIL": //inside a family record;
                  TheChild = new Child();
                  TheChild.ChildID = sData;
                  TheChild.FamilyID = _xrefid;
                  MyChildren.Add(TheChild);
                  if (MyFamilies[_xrefid].HasChildren == false)
                  {
                     MyFamilies[_xrefid].HasChildren = true;
                  }
                  break;
               case "CHAN":
                  EventType = LifeEvent.EventTypes.etChange;
                  break;
               case "CONC": //concatenation of a note;
                  if (RecType == RecordTypes.rtNOTE)
                  {
                     try
                     {
                        sTempData = MyNotes[_xrefid].NoteText;
                        MyNotes[_xrefid].NoteText = sTempData + sData;
                     }
                     catch
                     {
                        //this is necessary because FTW incorrectly places source notes at level 0
                     }
                  }
                  if (RecType == RecordTypes.rtINDI)
                  { //added for handling gedcoms from PAF
                     if ((_tag2 == "SOUR" || _tag1 == "SOUR") && _prevtag != "TEXT")
                     {
                        sTempData = MyIndividuals[_xrefid].Sources[_prevsrcid].Note;
                        MyIndividuals[_xrefid].Sources[_prevsrcid].Note = sTempData + sData;
                     }
                     else if (_prevtag == "TEXT")
                     {
                        sTempData = MyIndividuals[_xrefid].Sources[_prevsrcid].SourceText;
                        MyIndividuals[_xrefid].Sources[_prevsrcid].SourceText = sTempData + sData;
                     }
                     else if (_isevent == true)
                     {
                        sTempData = MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventNote;
                        MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventNote = sTempData + sData;
                     }
                     else
                     {
                        if (_filesrc != "TMG" && _filesrc != "LEG") //added in 8.0
                        {
                           sTempData = MyIndividuals[_xrefid].Notes;
                           MyIndividuals[_xrefid].Notes = sTempData + sData;
                        }
                        else
                        {
                           TheNote = new Note();
                           TheNote.ID = _xrefid;
                           //this should fail if the the note has already been added to the collection
                           MyNotes.Add(TheNote);

                           sTempData = MyNotes[_xrefid].NoteText;
                           MyNotes[_xrefid].NoteText = sTempData + sData;
                        }
                     }
                  }
                  if (RecType == RecordTypes.rtSOUR)
                  {
                     switch (_prevtag)
                     {
                        case "TITL":
                           sTempData = MySources[_xrefid].Title;
                           MySources[_xrefid].Title = sTempData + sData;
                           break;
                        case "PUBL":
                           sTempData = MySources[_xrefid].PublicationInfo;
                           MySources[_xrefid].PublicationInfo = sTempData + sData;
                           break;
                     }
                  }
                  break;
               case "CONT":
                  //continuation of a previous piece of data
                  //could be an address or even a note
                  switch (_prevtag)
                  {
                     case "ADDR":
                        if (RecType == RecordTypes.rtINDI)
                        {
                           sTempData = MyIndividuals[_xrefid].Address;
                           MyIndividuals[_xrefid].Address = sTempData + "<br>" + sData;
                        }
                        break;
                     case "NOTE":
                        if (RecType == RecordTypes.rtNOTE)
                        {
                           sTempData = MyNotes[_xrefid].NoteText;
                           MyNotes[_xrefid].NoteText = sTempData + "<br>" + sData;
                        }
                        if (RecType == RecordTypes.rtINDI)
                        {
                           if (_tag2 == "SOUR" || _tag1 == "SOUR")
                           {
                              sTempData = MyIndividuals[_xrefid].Sources[_prevsrcid].Note;
                              MyIndividuals[_xrefid].Sources[_prevsrcid].Note = sTempData + sData;
                           }
                           else if (_isevent == true)
                           {
                              sTempData = MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventNote;
                              MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventNote = sTempData + " " + sData;
                           }
                           else
                           {
                              TheNote = new Note();
                              TheNote.ID = _xrefid;
                              //this should fail if the the note has already been added to the collection
                              MyNotes.Add(TheNote);

                              sTempData = MyNotes[_xrefid].NoteText;
                              MyNotes[_xrefid].NoteText = sTempData + "<br>" + sData;
                           }
                        }
                        if (RecType == RecordTypes.rtSOUR)
                        { //added in 3.01
                           sTempData = MySources[_xrefid].Note;
                           MySources[_xrefid].Note = sTempData + "<br>" + sData;
                        }
                        break;
                     case "AUTH": //author of source;
                        if (RecType == RecordTypes.rtSOUR)
                        {
                           sTempData = MySources[_xrefid].Author;
                           MySources[_xrefid].Author = sTempData + "<br>" + sData;
                        }
                        break;
                     case "TITL"://title of source;
                        if (RecType == RecordTypes.rtSOUR)
                        {
                           sTempData = MySources[_xrefid].Title;
                           MySources[_xrefid].Title = sTempData + "<br>" + sData;
                        }
                        break;
                     case "TEXT"://text from source;
                        if (RecType == RecordTypes.rtSOUR)
                        {
                           sTempData = MySources[_xrefid].SourceText;
                           MySources[_xrefid].SourceText = sTempData + "<br>" + sData;
                        }
                        else if (RecType == RecordTypes.rtINDI)
                        {
                           sTempData = MyIndividuals[_xrefid].Sources[_prevsrcid].SourceText;
                           MyIndividuals[_xrefid].Sources[_prevsrcid].SourceText = sTempData + sData;
                        }
                        break;
                     case "PAGE"://used by tmg for citations;
                        if (RecType == RecordTypes.rtINDI)
                        {
                           sTempData = MyIndividuals[_xrefid].Sources[_prevsrcid].Page;
                           MyIndividuals[_xrefid].Sources[_prevsrcid].Page = sTempData + " " + sData;
                        }
                        break;
                     default:
                        break;
                     //there are others but we will deal with them later
                  }
                  break;
               case "DATA":
                  //when a source appears in a individual record
                  //and text is associeted with the source note
                  //need special handling for this
                  break;
               case "DATE":
                  if (RecType != RecordTypes.rtHEAD)
                  {
                     if (sf.IsDate(sData))
                     {
                        sData = sf.DateValue(sData).ToString("MMMM dd, yyyy");
                     }
                     else
                     {
                        //added in 2.5
                        sData = FixDate(sData);
                     }
                     switch (EventType)
                     {
                        case LifeEvent.EventTypes.etUnknown:
                           switch (RecType)
                           {
                              case RecordTypes.rtINDI:
                                 MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                                 break;
                              case RecordTypes.rtFAM:
                                 MyFamilies[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                                 break;
                           }
                           break;
                        case LifeEvent.EventTypes.etDeathOfSpouse:
                           if (RecType == RecordTypes.rtFAM) MyFamilies[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etBirth:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].BirthDateText = sData;
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etDeath:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].DeathDateText = sData;
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etBurial:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etOccupation:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etMarriage:
                           if (RecType == RecordTypes.rtFAM) MyFamilies[_xrefid].MarriageDateText = sData;
                           break;
                        case LifeEvent.EventTypes.etResidence:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etDivorce:
                           if (RecType == RecordTypes.rtFAM) MyFamilies[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etImmigration:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etMilitary:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etOther:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etElected:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etExcommunicated:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etMission:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etBaptismLDS:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etBaptism:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etBar_Mitzvah:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etBat_Mitzvah:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etBlessing:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etCaste:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etCensus:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etChristening:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etConfirmation:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etConfirmationLDS:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etCremation:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etEducation:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etEmigration:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etEndowmentLDS:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etFirstCommunion:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etGraduation:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etNaturalization:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etOrdination:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etProbate:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etProperty:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etReligion:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etRetirement:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etSealedToParentsLDS:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etSSN:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etWill:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
                           break;
                        case LifeEvent.EventTypes.etChange:
                           if (RecType == RecordTypes.rtINDI)
                           {
                              dtTempDate = sf.DateValue(sData);
                              if (dtTempDate > MyIndividuals[_xrefid].LastChangeDate)
                              {
                                 MyIndividuals[_xrefid].LastChangeDate = dtTempDate;
                              }
                           }
                           if (RecType == RecordTypes.rtFAM)
                           {
                              dtTempDate = sf.DateValue(sData);
                              if (dtTempDate > MyFamilies[_xrefid].LastChangeDate)
                              {
                                 MyFamilies[_xrefid].LastChangeDate = dtTempDate;
                              }
                           }
                           break;
                     }
                  }
                  else
                  {
                     MyFileInfo.CreationDate = sData;
                  }
                  break;
               case "DEAT":
                  EventType = LifeEvent.EventTypes.etDeath;

                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Death";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "DIV": //occurs inside a family record;
                  EventType = LifeEvent.EventTypes.etDivorce;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Divorced";
                  if (RecType == RecordTypes.rtFAM) MyFamilies[_xrefid].LifeEvents.Add(NewEvent);
                  if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "EMAIL":
                  if (RecType == RecordTypes.rtSUBM)
                  {
                     MyFileInfo.SubmitterEmail = sData;
                  }
                  break;
               case "EVEN":
                  //this is a special event defined by type
                  //there could be many of these and this version
                  //currently handles only one
                  if (RecType == RecordTypes.rtINDI)
                  {
                     EventType = LifeEvent.EventTypes.etOther;
                     _currevent++;
                     NewEvent = new LifeEvent();
                     NewEvent.ID = _xrefid + _currevent.ToString();
                     NewEvent.EventType = EventType;
                     NewEvent.EventText = sData;
                     MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                     _isevent = true;
                  }
                  break;
               case "FAMC":
                  MyIndividuals[_xrefid].FamilyID = sData;//added in ver 1.2;
                  TheChild = new Child();
                  TheChild.ChildID = _xrefid;
                  TheChild.FamilyID = sData;
                  MyChildren.Add(TheChild);
                  break;
               case "FAMS":
                  //individual is a spouse in a particular family
                  //attempt to create a new family
                  TheFamily = new Family();
                  TheFamily.ID = sData;
                  MyFamilies.Add(TheFamily);
                  MyIndividuals[_xrefid].HasOwnFamily = true;
                  MyIndividuals[_xrefid].FamList.Add(sData, sData);
                  switch (MyIndividuals[_xrefid].Sex)
                  {
                     case "M":
                        MyFamilies[sData].Husband = _xrefid;
                        break;
                     case "F":
                        MyFamilies[sData].Wife = _xrefid;
                        break;
                  }
                  break;
               case "FILE":
                  if (RecType == RecordTypes.rtHEAD)
                  {
                     MyFileInfo.SourceFile = sData;
                  }
                  break;
               case "HUSB":
                  MyFamilies[_xrefid].Husband = sData;
                  break;
               case "IMMI":
                  EventType = LifeEvent.EventTypes.etImmigration;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Immigrated";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "MARR":
                  EventType = LifeEvent.EventTypes.etMarriage;
                  break;
               case "MEDI":
                  //media of the source
                  if (RecType == RecordTypes.rtSOUR)
                  {
                     MySources[_xrefid].Media = sData;
                  }
                  break;
               case "NAME":
                  if (RecType == RecordTypes.rtHEAD)
                  {
                     MyFileInfo.SourceName = sData;
                  }
                  if (RecType == RecordTypes.rtSUBM)
                  {
                     MyFileInfo.SubmitterName = sData;
                  }
                  if (iLevel == 1)
                  {
                     if (RecType == RecordTypes.rtINDI)
                     {
                        MyIndividuals[_xrefid].Surname = sData; //in case it is just a single name (ex. <Living>)

                        //extract the surname and the forenames
                        posDelim = sf.InStr(sData, SLASH);
                        if (posDelim != 0)
                        {
                           MyIndividuals[_xrefid].Forenames = sf.Trim(sf.Left(sData, posDelim - 1));
                           MyIndividuals[_xrefid].Surname = sf.Trim(sf.Right(sData, sf.Len(sData) - posDelim));
                        }
                        posDelim = sf.InStr(MyIndividuals[_xrefid].Surname, SLASH);
                        if (posDelim != 0)
                        {
                           sTempData = MyIndividuals[_xrefid].Surname;
                           MyIndividuals[_xrefid].Surname = sf.Trim(sf.Left(MyIndividuals[_xrefid].Surname, posDelim - 1));
                        }

                        //look for a comma
                        posDelim = sf.InStr(MyIndividuals[_xrefid].Forenames, ",");
                        if (posDelim != 0)
                        {
                           MyIndividuals[_xrefid].Suffix = sf.Trim(sf.Right(MyIndividuals[_xrefid].Forenames, sf.Len(MyIndividuals[_xrefid].Forenames) - posDelim));
                           MyIndividuals[_xrefid].Forenames = sf.Trim(sf.Left(MyIndividuals[_xrefid].Forenames, posDelim - 1));
                        }

                        if (m_cfg.SurnamesAllCaps && MyIndividuals[_xrefid].Surname != "")
                        {
                           MyIndividuals[_xrefid].Surname = sf.UCase(MyIndividuals[_xrefid].Surname);
                        }
                     }
                  }
                  break;
               case "NATI":
                  EventType = LifeEvent.EventTypes.etNationality;
                  break;
               case "NOTE":
                  if (RecType == RecordTypes.rtINDI)
                  {
                     if (_tag2 == "SOUR" || _tag1 == "SOUR")
                     {
                        MyIndividuals[_xrefid].Sources[_prevsrcid].Note = sData;
                     }
                     else
                     {
                        switch (_filesrc)
                        {
                           case "PAF":
                              TheNote = new Note(); //trying to fix problem btwn the way that PAF and FTW do notes;
                              TheNote.ID = _xrefid;
                              MyNotes.Add(TheNote); //this should fail if the the note has already been added to the collection;
                              MyNotes[_xrefid].NoteText = sData;
                              MyIndividuals[_xrefid].Notes = _xrefid;
                              break;
                           case "FTW":
                              MyIndividuals[_xrefid].Notes = sData;
                              break;
                           case "LEG":
                           case "TMG":
                              if ((_tag2 == "NOTE" || _tag1 == "NOTE") && _isevent == true)
                              {
                                 MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventNote = sData;
                              }
                              else
                              {
                                 TheNote = new Note();
                                 TheNote.ID = _xrefid;
                                 MyNotes.Add(TheNote); //this should fail if the the note has already been added to the collection;
                                 MyNotes[_xrefid].NoteText = sData;
                                 MyIndividuals[_xrefid].Notes = _xrefid;

                              }
                              break;
                        }
                     }
                  }
                  else if (RecType == RecordTypes.rtFAM)
                  { //added ver. 2.07 to handle marriage notes
                     switch (_filesrc)
                     {
                        case "PAF":
                           TheNote = new Note(); //trying to fix problem btwn the way that PAF and FTW do notes;
                           TheNote.ID = _xrefid;
                           MyNotes.Add(TheNote);//this should fail if the the note has already been added to the collection;
                           MyNotes[_xrefid].NoteText = sData;
                           MyFamilies[_xrefid].Notes = _xrefid;
                           break;
                        case "FTW":
                           MyFamilies[_xrefid].Notes = sData;
                           break;
                        case "LEG":
                           MyFamilies[_xrefid].Notes = sData;
                           break;
                     }
                  }
                  else if (RecType == RecordTypes.rtSOUR)
                  { //added in 3.01
                     MySources[_xrefid].Note = sData;
                  }
                  else if (RecType == RecordTypes.rtNOTE)
                  {
                     MyNotes[_xrefid].NoteText = sData;
                  }
                  break;
               case "OCCU":
                  EventType = LifeEvent.EventTypes.etOccupation;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Occupation: " + sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "PAGE":
                  //used in source not used here
                  //started using in 3.01
                  if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].Sources[_prevsrcid].Page = sData;
                  break;
               case "ABBR":
                  //used in source not used here
                  //started using in 5.01
                  if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].Sources[_prevsrcid].Abbreviation = sData;
                  break;
               case "PUBL":
                  if (RecType == RecordTypes.rtSOUR)
                  {
                     MySources[_xrefid].PublicationInfo = sData;
                  }
                  break;
               case "PLAC":
                  if (RecType != RecordTypes.rtHEAD)
                  {
                     switch (EventType)
                     {

                        case LifeEvent.EventTypes.etUnknown:
                           switch (RecType)
                           {
                              case RecordTypes.rtINDI:
                                 MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                                 break;
                              case RecordTypes.rtFAM:
                                 MyFamilies[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                                 break;
                           }
                           break;
                        case LifeEvent.EventTypes.etDeathOfSpouse:
                           if (RecType == RecordTypes.rtFAM) MyFamilies[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etBirth:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].BirthPlace = sData;
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etDeath:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].DeathPlace = sData;
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etBurial:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etOccupation:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etMarriage:
                           if (RecType == RecordTypes.rtFAM) MyFamilies[_xrefid].MarriagePlace = sData;
                           break;
                        case LifeEvent.EventTypes.etResidence:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etDivorce:
                           if (RecType == RecordTypes.rtFAM) MyFamilies[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etNationality:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].Nationality = sData;
                           break;
                        case LifeEvent.EventTypes.etImmigration:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etMilitary:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etOther:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etElected:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etExcommunicated:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etMission:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etBaptismLDS:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etBaptism:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etBar_Mitzvah:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etBat_Mitzvah:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etBlessing:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etCaste:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etCensus:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etChristening:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etConfirmation:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etConfirmationLDS:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etCremation:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etEducation:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etEmigration:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etEndowmentLDS:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etFirstCommunion:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etGraduation:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etNaturalization:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etOrdination:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etProbate:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etProperty:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etReligion:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etRetirement:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etSealedToParentsLDS:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etSSN:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                        case LifeEvent.EventTypes.etWill:
                           if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
                           break;
                     }
                  }
                  break;
               case "REFN":
                  if (RecType == RecordTypes.rtINDI)
                  {
                     MyIndividuals[_xrefid].ReferenceNumber = sData;
                  }
                  if (RecType == RecordTypes.rtFAM)
                  {
                     MyFamilies[_xrefid].ReferenceNumber = sData;
                  }
                  break;
               case "REPO":
                  //used in sources
                  break;
               case "RESI":
                  EventType = LifeEvent.EventTypes.etResidence;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Residence";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "SEX":
                  MyIndividuals[_xrefid].Sex = sData;
                  break;
               case "SOUR":
                  if (RecType == RecordTypes.rtHEAD)
                  { //this is the source of the GEDCOM file
                     _filesrc = sf.UCase(sf.Left(sData, 3));
                     MyFileInfo.Source = sData;

                  }
                  if (sf.Left(sData, 1) == "@")
                  {
                     TheSource = new Source();
                     TheSource.ID = sData;
                     _prevsrcid = sData;
                     TheSource.EventTag = _taglevel1;
                     switch (RecType)
                     {
                        case RecordTypes.rtINDI: MyIndividuals[_xrefid].Sources.Add(TheSource);
                           break;
                        case RecordTypes.rtFAM: MyFamilies[_xrefid].Sources.Add(TheSource);
                           break;
                     }
                  }
                  break;
               case "TEXT":
                  if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].Sources[_prevsrcid].SourceText = sData;
                  break;
               case "TIME":
                  if (RecType == RecordTypes.rtHEAD)
                  {
                     MyFileInfo.CreationTime = sData;
                  }
                  break;
               case "TITL":
                  if (RecType == RecordTypes.rtSOUR)
                  {
                     MySources[_xrefid].Title = sData;
                  }
                  break;
               case "TYPE":
                  if (_prevtag == "EVEN" && RecType == RecordTypes.rtINDI)
                  {
                     if (sData == "Occupation")
                     {
                        MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventType = LifeEvent.EventTypes.etOccupation;
                        sTempData = MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventText;
                        MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventText = "Occupation: " + sTempData;
                     }
                     else
                     {
                        sTempData = MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventText;
                        MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventText = sData + "&nbsp;" + sTempData;
                     }
                  }
                  break;
               case "VERS":
                  //version of software that produced this
                  if (RecType == RecordTypes.rtHEAD && MyFileInfo.Version == "")
                  {
                     MyFileInfo.Version = sData;
                  }
                  break;
               case "WIFE":
                  MyFamilies[_xrefid].Wife = sData;
                  break;
               case "_ELEC":
                  EventType = LifeEvent.EventTypes.etElected;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Elected";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "_EXCM":
                  EventType = LifeEvent.EventTypes.etExcommunicated;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Excommunicated";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "_MISN":
                  EventType = LifeEvent.EventTypes.etMission;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Mission";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "BAPL":
                  EventType = LifeEvent.EventTypes.etBaptismLDS;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Baptism (LDS)";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "BAPM":
                  EventType = LifeEvent.EventTypes.etBaptism;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Baptism";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "BARM":
                  EventType = LifeEvent.EventTypes.etBar_Mitzvah;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Bar-Mitzvah";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "BASM":
                  EventType = LifeEvent.EventTypes.etBat_Mitzvah;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Bat-Mitzvah";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "BLES":
                  EventType = LifeEvent.EventTypes.etBlessing;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Blessing";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "CAST":
                  EventType = LifeEvent.EventTypes.etCaste;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Caste";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "CENS":
                  EventType = LifeEvent.EventTypes.etCensus;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Census";
                  NewEvent.EventDescription = sData;
                  if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  if (RecType == RecordTypes.rtFAM) MyFamilies[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "CHR":
                  EventType = LifeEvent.EventTypes.etChristening;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Christening";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "CONF":
                  EventType = LifeEvent.EventTypes.etConfirmation;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Confirmation";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "CONL":
                  EventType = LifeEvent.EventTypes.etConfirmationLDS;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Confirmation (LDS)";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "CREM":
                  EventType = LifeEvent.EventTypes.etCremation;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Cremation";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "EDUC":
                  EventType = LifeEvent.EventTypes.etEducation;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Education";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "EMIG":
                  EventType = LifeEvent.EventTypes.etEmigration;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Emigration";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "ENDL":
                  EventType = LifeEvent.EventTypes.etEndowmentLDS;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Endowment (LDS)";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "FCOM":
                  EventType = LifeEvent.EventTypes.etFirstCommunion;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "First Communion";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "GRAD":
                  EventType = LifeEvent.EventTypes.etGraduation;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Graduation";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "NATU":
                  EventType = LifeEvent.EventTypes.etNaturalization;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Naturalization";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "ORDN":
                  EventType = LifeEvent.EventTypes.etOrdination;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Ordination";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "PROB":
                  EventType = LifeEvent.EventTypes.etProbate;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Probate";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "PROP":
                  EventType = LifeEvent.EventTypes.etProperty;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Property";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "RELI":
                  EventType = LifeEvent.EventTypes.etReligion;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Religion";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "RETI":
                  EventType = LifeEvent.EventTypes.etRetirement;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Retirement";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "SLGC":
                  EventType = LifeEvent.EventTypes.etSealedToParentsLDS;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Sealed to parents (LDS)";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "SSN":
                  EventType = LifeEvent.EventTypes.etSSN;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "SSN";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
               case "WILL":
                  EventType = LifeEvent.EventTypes.etWill;
                  _currevent++;
                  NewEvent = new LifeEvent();
                  NewEvent.ID = _xrefid + _currevent.ToString();
                  NewEvent.EventType = EventType;
                  NewEvent.EventText = "Will";
                  NewEvent.EventDescription = sData;
                  MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
                  _isevent = true;
                  break;
            }
         }

         //don't count continuation and concatenation
         //as previous tag
         if (sTag != "CONT" && sTag != "CONC")
         {
            _prevtag = sTag;
         }

      }

      #endregion

      #region Save as HTM
      /// <summary>
      /// called by main to build the web pages
      /// </summary>
      /// 		
      public void SaveAsHTM()
      {

         try
         {

            if (m_cfg.CreateGendexFile == true)
            {
               MyGendices = new Gendices();
            }

            if (m_cfg.SourcesInNewWindow == false) 
               _srcTarget = "_self"; 
            else 
               _srcTarget = "_blank";

            FireStatusMessage("Writing HTML Pages...");

            _didCancel = false;

            string[] TestFiles = Directory.GetFiles(m_cfg.HtmlPath, "*.htm*");

            if (TestFiles.Length != 0)
            {
               FireStatusMessage("The directory " + m_cfg.HtmlPath + " contains HTML files. Some files may be overwritten.");
            }

            FireStatusMessage("Building Family Pages..");
            if (BuildFamilyPages() == false)
            {
               goto HTML_CLEAN_UP;
            }
            if (_didCancel)
            {
               goto HTML_CLEAN_UP;
            }
            FireStatusMessage("Building Index Page...");
            BuildIndexEach();
            if (_didCancel) goto HTML_CLEAN_UP;
            FireStatusMessage("Building Sources Page...");
            BuildBiblio();
            if (_didCancel) goto HTML_CLEAN_UP;
            FireStatusMessage("Building Surname Page...");
            BuildSurnamePage();
            if (_didCancel) goto HTML_CLEAN_UP;
            if (m_cfg.CreateStatsPage == true)
            {
               FireStatusMessage("Building Stats Page...");
               BuildStatisticsPage();
               if (_didCancel) goto HTML_CLEAN_UP;
            }
            BuildTableOfContents();
            if (_didCancel) goto HTML_CLEAN_UP;
            if (m_cfg.CreateGendexFile == true)
            {
               FireStatusMessage("Building Gendex file...");
               BuildGendexFile();
               if (_didCancel) goto HTML_CLEAN_UP;
            }

            //added in 3.01
            if (m_cfg.CreateChronoPage == true)
            {
               FireStatusMessage("Building Chronology Page...");
               BuildTimeLinePage();
               if (_didCancel) goto HTML_CLEAN_UP;
            }


            //added in 3.02
            if (m_cfg.CreateLocPage == true)
            {
               FireStatusMessage("Building Locations Page...");
               BuildLocationsReport();
               if (_didCancel) goto HTML_CLEAN_UP;
            }

            //added in 3.03
            if (m_cfg.CreateOccupationsPage == true)
            {
               FireStatusMessage("Building Occupations Page...");
               BuildOccupationsReport();
               if (_didCancel) goto HTML_CLEAN_UP;
            }

            _didCancel = false;
            FireStatusMessage("HTML files have been created in " + m_cfg.HtmlPath + ".");
            return;

         HTML_CLEAN_UP:
            _didCancel = false;

            return;
         }
         catch (Exception ex)
         {
            FireStatusMessage("The following error occured in SaveAsHTML while processing the GEDCOM file:" + '\n' + "Error: " + ex.Message);
            FireStatusMessage("Incomplete");
            _didCancel = false;
         }
      }
      #endregion

      #region Page Building methods

      /// <summary>
      /// Summary of BuildOccupationsReport.
      /// </summary>
      /// 		
      private void BuildOccupationsReport()
      {
         string sFile;
         int iOccCount;
         int iNumOcc;
         string sCurrOcc;
         string sPrevOcc;
         string sOccupation;
         string sFile2;
         const char QUOTE = '"';

         //build a list of occupations
         GetOccupations();
         iNumOcc = MyOccupations.Count;
         if (iNumOcc == 0) return;
         SortedList sl = new SortedList(iNumOcc);
         sl.Clear();

         for (iOccCount = 0; iOccCount <= iNumOcc - 1; iOccCount++)
         {
            sl.Add(MyOccupations[iOccCount].OccupationTitle + CreateGUIDKey(), iOccCount);
         } // iOccCount

         if (m_cfg.FamFilePrefix == "fam")
         {
            sFile = m_cfg.HtmlPath + "\\occupations.html";
         }
         else
         {
            sFile = m_cfg.HtmlPath + "\\" + m_cfg.FamFilePrefix + "_occupations.html";
         }

         FileStream fs1 = new FileStream(sFile, FileMode.Create);
         StreamWriter sw1 = new StreamWriter(fs1);

         sFile2 = m_cfg.HtmlPath + "\\occ_report.txt";

         FileStream fs2 = new FileStream(sFile2, FileMode.Create);
         StreamWriter sw2 = new StreamWriter(fs2);

         //file header
         sw1.WriteLine("<HTML>");
         sw1.WriteLine("<HEAD>");
         if (m_cfg.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
         sw1.WriteLine("<TITLE>Occupations Report</TITLE>");
         sw1.WriteLine("<META NAME=" + QUOTE + " Generator" + QUOTE + " CONTENT=" + QUOTE + " UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");
         sw1.WriteLine("</HEAD>");
         if (m_cfg.UseBackground)
         {
            sw1.WriteLine("<body background=" + QUOTE + m_cfg.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         sw1.WriteLine("<p><a name=" + QUOTE + "TOP" + QUOTE + ">&nbsp;</a></p>");
         if (m_cfg.UseBanner)
         {
            sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + m_cfg.BannerFile + QUOTE + "></p>");
         }
         sw1.WriteLine("<h1><p align=" + QUOTE + "center" + QUOTE + ">Occupations</p></h1>");
         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sPrevOcc = "#";
         for (iOccCount = 0; iOccCount <= iNumOcc - 1; iOccCount++)
         {
            if (_didCancel) goto BUILDOCC_EXIT;
            //strip off GUID
            sOccupation = sf.Left((string)sl.GetKey(iOccCount), sf.Len((string)sl.GetKey(iOccCount)) - 36);
            if (sOccupation != "")
            {
               sCurrOcc = sOccupation;
               if (sPrevOcc != sCurrOcc)
               {
                  sw1.WriteLine("</ul>");  //end prev list;
                  sw1.Write("<H2>");
                  sw1.Write(sCurrOcc);
                  sw2.WriteLine(sCurrOcc);
                  sw1.WriteLine("</H2>");
                  sPrevOcc = sCurrOcc;
                  sw1.WriteLine("<ul>");  //start a new list;
               }
               sw1.WriteLine("<li>" + MyOccupations[(int)sl.GetByIndex(iOccCount)].PersonName + "</li>");
            }
         } // iOccCount

         sw1.WriteLine("</ul>");  //end prev list;

         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<EM><CENTER>");
         if (m_cfg.FamFilePrefix == "fam")
         {
            sw1.WriteLine("<A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<A HREF=" + QUOTE + m_cfg.FamFilePrefix + "_ind_idx.html" + QUOTE + ">");
         }
         sw1.WriteLine("Index");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<EM><CENTER>");

         sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");

         sw1.WriteLine("Table Of Contents");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<HR NOSHADE SIZE=1>");

         if (m_cfg.AddUserCopyright == true && m_cfg.AuthorsName != "")
         {
            sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
            sw1.Write("Copyright &copy; " + DateTime.Now.Year.ToString() + "&nbsp;");
            if (m_cfg.AuthorsEmail != "")
            {
               sw1.Write("<A href=" + QUOTE + "mailto:" + m_cfg.AuthorsEmail + QUOTE + ">");
               sw1.Write(m_cfg.AuthorsName);
               if (m_cfg.AuthorsEmail != "") sw1.Write("</A>");
               sw1.WriteLine("</CENTER></P></FONT>");
            }
         }

         sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
         sw1.WriteLine("This page was created on " + DateTime.Now.ToShortDateString() + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00")); //);
         sw1.WriteLine("Copyright &copy; 1999-2007 D. M. DeBacker");
         sw1.WriteLine("</CENTER></P></FONT>");
         sw1.WriteLine("</BODY>");
         sw1.WriteLine("</HTML>");

      BUILDOCC_EXIT:
         sw1.Close();
         fs1.Close();
         sw2.Close();
         fs2.Close();
      }


      /// <summary>
      /// Summary of GetOccupations.
      /// </summary>
      /// 		
      private void GetOccupations()
      {
         //added in 3.03
         int iCnt;
         int jCnt;
         int iTotItems;
         string sEventDetails;
         string sOccupation;
         string sName;
         int iNumEvents;

         char Q = '"';

         //wipe everything out
         MyOccupations = new Occupations();

         //life events
         iTotItems = MyIndividuals.Count;

         if (iTotItems != 0)
         {
            for (iCnt = 0; iCnt <= iTotItems - 1; iCnt++)
            {
               iNumEvents = MyIndividuals[iCnt].LifeEvents.Count;
               if (iNumEvents != 0)
               {
                  for (jCnt = 0; jCnt <= iNumEvents - 1; jCnt++)
                  {
                     sEventDetails = "";
                     if (MyIndividuals[iCnt].LifeEvents[jCnt].EventType == LifeEvent.EventTypes.etOccupation)
                     {
                        if (m_cfg.OccLocEqualsOccText == true)
                        {
                           sOccupation = sf.Trim(MyIndividuals[iCnt].LifeEvents[jCnt].EventPlace);
                        }
                        else
                        {
                           sOccupation = sf.Trim(MyIndividuals[iCnt].LifeEvents[jCnt].EventText);
                        }

                        if (sf.Trim(sOccupation) == "") break;

                        sOccupation = FixOccupation(sOccupation);

                        sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
                        if (MyIndividuals[iCnt].Suffix != "")
                        {
                           sName = sName + ", " + MyIndividuals[iCnt].Suffix;
                        }

                        if (m_cfg.ChronoLinks == true) sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
                        sEventDetails = sEventDetails + sName;
                        if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "</a>";

                        MyOccupations.Add(sOccupation, sEventDetails, CreateGUIDKey());
                     }
                  } // jCnt				
               } // iCnt
            }
         }
      }


      /// <summary>
      /// Summary of BuildFamilyPages.
      /// </summary>
      /// 		
      private bool BuildFamilyPages()
      {
         string sFile;
         int iFamCount;
         int iChildCount;
         int iNumFams;
         string FamRefID;
         string sTitle;
         string sHusband;
         string sWife;
         string sChTitle;
         string sChHusband;
         string sChWife;
         string sLink;
         ArrayList sLinks = new ArrayList();
         ArrayList sLnkFamID = new ArrayList();
         string sFather;
         string sMother;
         int iNumLinks;
         int iLinkcount;
         string sParents;
         bool bHasKids;
         int iNumEvents;
         int iNumSrcs;
         //			Surname NewSurname;
         string sSrnLink;
         bool bDoNotes;
         string sFamKey;
         bool bNotesOkay;
         string sListFile;
         string sChildName;
         bool bDidLine = false;
         string sGenUrl;
         DateTime dtLastChangeDate;
         //ver 4
         int NumOtherMarriages;
         ArrayList aryOtherFams;
         int iOtherCnt;

         FileStream fs1 = null;
         StreamWriter sw1 = null;
         FileStream fs2 = null;
         StreamWriter sw2 = null;


         try
         {
            iNumFams = MyFamilies.Count;

            char QUOTE = '"';

            if (m_cfg.CreateListReport == true)
            {
               sListFile = m_cfg.HtmlPath + "\\list.txt";

               fs2 = new FileStream(sListFile, FileMode.Create);
               sw2 = new StreamWriter(fs2);
            }

            if (iNumFams == 0) return true;
            for (iFamCount = 0; iFamCount <= iNumFams - 1; iFamCount++)
            {

               if (_didCancel) goto BUILDFAMILY_EXIT;
               bHasKids = false;
               //get the fam id
               FamRefID = MyFamilies[iFamCount].ID;

               dtLastChangeDate = MyFamilies[iFamCount].LastChangeDate; //start the last changed date;

               //establish the file name
               sFile = sf.Right(FamRefID, sf.Len(FamRefID) - 2);
               sFile = sf.Left(sFile, sf.Len(sFile) - 1);
               int iFileNumber = System.Convert.ToInt32(sFile); //added on v.6;
               sFile = iFileNumber.ToString("000");
               if (localSettings.FirstFamily == 0)
               {
                  localSettings.FirstFamily = System.Convert.ToInt32(sFile);
               }
               if (System.Convert.ToInt32(sFile) < localSettings.FirstFamily)
               {
                  localSettings.FirstFamily = System.Convert.ToInt32(sFile);
               }
               sSrnLink = m_cfg.FamFilePrefix + sFile + ".html";
               sFile = m_cfg.HtmlPath + "\\" + m_cfg.FamFilePrefix + sFile + ".html";
               FireStatusMessage("Building Family Page " + LongDirFix(sFile, 32) + "...");

               //the husband
               if (MyFamilies[iFamCount].Husband != "?")
               {
                  sHusband = MyIndividuals[MyFamilies[iFamCount].Husband].Forenames + " " + MyIndividuals[MyFamilies[iFamCount].Husband].Surname;
                  if (MyIndividuals[MyFamilies[iFamCount].Husband].Suffix != "")
                  {
                     sHusband = sHusband + ", " + MyIndividuals[MyFamilies[iFamCount].Husband].Suffix;
                  }

                  //modified in ver 2.05 for counting surnames
                  //THIS IS ALL WRONG - THIS IS ONLY COUNTING HUSBAND AND WIFE - NOT INDIVIDUALS
                  //						NewSurname = new Surname();
                  //						NewSurname.FamilyName = sf.UCase(MyIndividuals[MyFamilies[iFamCount].Husband].Surname);
                  //						NewSurname.FirstLink = sSrnLink;
                  //						if ( MySurnames.Add(NewSurname) == false ) 
                  //						{
                  //							//if it failed to add then increment it
                  //							MySurnames[NewSurname.FamilyName].NumItems = MySurnames[NewSurname.FamilyName].NumItems + 1;
                  //						}
                  //						NewSurname = null;

                  if (MyIndividuals[MyFamilies[iFamCount].Husband].LastChangeDate > dtLastChangeDate) dtLastChangeDate = MyIndividuals[MyFamilies[iFamCount].Husband].LastChangeDate;

               }
               else
               {
                  sHusband = "?";
               }

               //the wife
               if (MyFamilies[iFamCount].Wife != "?")
               {
                  sWife = MyIndividuals[MyFamilies[iFamCount].Wife].Forenames + " " + MyIndividuals[MyFamilies[iFamCount].Wife].Surname;
                  if (MyIndividuals[MyFamilies[iFamCount].Wife].Suffix != "")
                  {
                     sWife = sWife + ", " + MyIndividuals[MyFamilies[iFamCount].Wife].Suffix;
                  }

                  //						NewSurname = new Surname();
                  //						NewSurname.FamilyName = sf.UCase(MyIndividuals[MyFamilies[iFamCount].Wife].Surname);
                  //						NewSurname.FirstLink = sSrnLink;
                  //						if ( MySurnames.Add(NewSurname) == false ) 
                  //						{
                  //							//if it failed to add then increment it
                  //							MySurnames[NewSurname.FamilyName].NumItems = MySurnames[NewSurname.FamilyName].NumItems + 1;
                  //						}
                  //						NewSurname = null;

                  if (MyIndividuals[MyFamilies[iFamCount].Wife].LastChangeDate > dtLastChangeDate) dtLastChangeDate = MyIndividuals[MyFamilies[iFamCount].Wife].LastChangeDate;
               }
               else
               {
                  sWife = "?";
               }

               //title of web page
               sTitle = sHusband + "\\" + sWife;

               if (m_cfg.DisplayMRIN == true)
               {
                  sTitle = sTitle + " (MRIN:" + FixRin(MyFamilies[iFamCount].ID) + ")";
               }

               //open the file
               fs1 = new FileStream(sFile, FileMode.Create);
               sw1 = new StreamWriter(fs1);

               //file header
               sw1.WriteLine("<HTML>");
               sw1.WriteLine("<HEAD>");
               if (m_cfg.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
               sw1.WriteLine("<TITLE>" + sTitle + "</TITLE>");
               sw1.WriteLine("<META NAME=" + QUOTE + " Generator" + QUOTE + " CONTENT=" + QUOTE + " UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");
               sw1.WriteLine("</HEAD>");
               if (m_cfg.UseBackground)
               {
                  sw1.WriteLine("<body background=" + QUOTE + m_cfg.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
               }
               else
               {
                  sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
               }
               if (m_cfg.UseBanner)
               {
                  sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + m_cfg.BannerFile + QUOTE + "></p>");
               }

               //husband details
               if (sHusband != "?")
               {
                  sw1.Write("<B>" + sHusband + "</B>");

                  if (m_cfg.DisplayRIN == true)
                  {
                     sw1.Write("&nbsp;(RIN: " + FixRin(MyIndividuals[MyFamilies[iFamCount].Husband].ID) + ")");
                  }

                  if (m_cfg.CreateListReport == true)
                  {
                     sw2.WriteLine("{0},{1},{2}", sHusband, MyIndividuals[MyFamilies[iFamCount].Husband].ReferenceNumber, sSrnLink);
                  }

                  if (m_cfg.CreateGendexFile == true)
                  {
                     //"GENDEX.txt"
                     sGenUrl = sSrnLink;
                     MyGendices.Add(sGenUrl, sf.UCase(MyIndividuals[MyFamilies[iFamCount].Husband].Surname), MyIndividuals[MyFamilies[iFamCount].Husband].Forenames + " /" + sf.UCase(MyIndividuals[MyFamilies[iFamCount].Husband].Surname) + "/", (MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText), (MyIndividuals[MyFamilies[iFamCount].Husband].BirthPlace), (MyIndividuals[MyFamilies[iFamCount].Husband].DeathDateText), (MyIndividuals[MyFamilies[iFamCount].Husband].DeathPlace), CreateGUIDKey());
                  }


                  //find his parents
                  sFamKey = MyIndividuals[MyFamilies[iFamCount].Husband].FamilyID + MyIndividuals[MyFamilies[iFamCount].Husband].ID;

                  {
                     Child child;
                     try
                     {
                        child = MyChildren[sFamKey];
                     }
                     catch
                     {
                        child = null;
                     }
                     if (child != null)
                     {
                        //he is in this family
                        sLink = "";
                        sParents = "";
                        sw1.Write(", son of ");
                        sLink = MyFamilies[child.FamilyID].ID;
                        sLink = sf.Right(sLink, sf.Len(sLink) - 2);
                        int iLinkNumber = System.Convert.ToInt32(sf.Left(sLink, sf.Len(sLink) - 1));
                        sLink = iLinkNumber.ToString("000");
                        sLink = m_cfg.FamFilePrefix + sLink + ".html";
                        if (sLink != "") sw1.WriteLine("<A HREF=" + QUOTE + sLink + QUOTE + ">");
                        if (MyFamilies[child.FamilyID].Husband != "?")
                        {
                           sFather = MyIndividuals[MyFamilies[child.FamilyID].Husband].Forenames + " " + MyIndividuals[MyFamilies[child.FamilyID].Husband].Surname;
                           sParents = sFather;
                           if (MyFamilies[child.FamilyID].Wife != "?")
                           {
                              sParents = sFather + " and ";
                           }
                        }
                        if (MyFamilies[child.FamilyID].Wife != "?")
                        {
                           sMother = MyIndividuals[MyFamilies[child.FamilyID].Wife].Forenames + " " + MyIndividuals[MyFamilies[child.FamilyID].Wife].Surname;
                           sParents = sParents + sMother;
                        }
                        sw1.WriteLine(sParents);
                        if (sLink != "") sw1.WriteLine("</A>,");
                     }
                     child = null;
                  }

                  if (MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText != "")
                  {
                     if (sf.IsDate(MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText))
                     {
                        sw1.Write(" was born  " + sf.DateValue(MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText).ToString("MMMM dd,yyyy"));
                     }
                     else
                     {
                        sw1.Write(" was born  " + MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText);
                     }
                  }
                  if (MyIndividuals[MyFamilies[iFamCount].Husband].BirthPlace != "")
                  {
                     sw1.Write(" in " + FixEstLoc((MyIndividuals[MyFamilies[iFamCount].Husband].BirthPlace)));
                     sw1.Write(". ");
                  }
                  else
                  {
                     sw1.Write(". ");
                  }
                  if (sWife != "?")
                  {
                     sw1.WriteLine("He married " + sWife);

                     if (MyFamilies[iFamCount].MarriageDateText != "")
                     {
                        sw1.Write(MyFamilies[iFamCount].MarriageDateText);
                     }
                     if (MyFamilies[iFamCount].MarriagePlace != "")
                     {
                        sw1.Write(" in " + FixEstLoc((MyFamilies[iFamCount].MarriagePlace)));
                        sw1.Write(". ");
                     }
                     else
                     {
                        sw1.Write(". ");
                     }
                  }
                  if (MyIndividuals[MyFamilies[iFamCount].Husband].DeathDateText != "" || MyIndividuals[MyFamilies[iFamCount].Husband].DeathPlace != "")
                  {
                     sw1.Write("He died " + MyIndividuals[MyFamilies[iFamCount].Husband].DeathDateText);
                     if (MyIndividuals[MyFamilies[iFamCount].Husband].DeathPlace != "")
                     {
                        sw1.Write(" in " + FixEstLoc((MyIndividuals[MyFamilies[iFamCount].Husband].DeathPlace)));
                     }
                     sw1.Write(". ");
                  }
               }

               //wife details
               if (sWife != "?")
               {
                  sw1.Write("<B>" + sWife + "</B>");

                  if (m_cfg.DisplayRIN == true)
                  {
                     sw1.Write("&nbsp;(RIN: " + FixRin(MyIndividuals[MyFamilies[iFamCount].Wife].ID) + ")");
                  }

                  if (m_cfg.CreateListReport == true)
                  {
                     sw2.WriteLine("{0},{1},{2}", sWife, MyIndividuals[MyFamilies[iFamCount].Wife].ReferenceNumber, sSrnLink);
                  }

                  if (m_cfg.CreateGendexFile == true)
                  {
                     //"GENDEX.txt"
                     sGenUrl = sSrnLink;
                     MyGendices.Add(sGenUrl, sf.UCase(MyIndividuals[MyFamilies[iFamCount].Wife].Surname), MyIndividuals[MyFamilies[iFamCount].Wife].Forenames + " /" + sf.UCase(MyIndividuals[MyFamilies[iFamCount].Wife].Surname) + "/", MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText, MyIndividuals[MyFamilies[iFamCount].Wife].BirthPlace, MyIndividuals[MyFamilies[iFamCount].Wife].DeathDateText, MyIndividuals[MyFamilies[iFamCount].Wife].DeathPlace, CreateGUIDKey());
                  }

                  //find her parents
                  sFamKey = MyIndividuals[MyFamilies[iFamCount].Wife].FamilyID + MyIndividuals[MyFamilies[iFamCount].Wife].ID;

                  {
                     Child child;
                     try
                     {
                        child = MyChildren[sFamKey];
                     }
                     catch { child = null; }
                     if (child != null)
                     {
                        //she is in this family
                        sLink = "";
                        sParents = "";
                        sw1.Write(", daughter of ");
                        sLink = MyFamilies[child.FamilyID].ID;
                        sLink = sf.Right(sLink, sf.Len(sLink) - 2);
                        int iLinkNumber = System.Convert.ToInt32(sf.Left(sLink, sf.Len(sLink) - 1));
                        sLink = iLinkNumber.ToString("000");
                        sLink = m_cfg.FamFilePrefix + sLink + ".html";
                        if (sLink != "") sw1.WriteLine("<A HREF=" + QUOTE + sLink + QUOTE + ">");
                        if (MyFamilies[child.FamilyID].Husband != "?")
                        {
                           sFather = MyIndividuals[MyFamilies[child.FamilyID].Husband].Forenames + " " + MyIndividuals[MyFamilies[child.FamilyID].Husband].Surname;
                           sParents = sFather;
                           if (MyFamilies[child.FamilyID].Wife != "?")
                           {
                              sParents = sParents + " and ";
                           }
                        }
                        if (MyFamilies[child.FamilyID].Wife != "?")
                        {
                           sMother = MyIndividuals[MyFamilies[child.FamilyID].Wife].Forenames + " " + MyIndividuals[MyFamilies[child.FamilyID].Wife].Surname;
                           sParents = sParents + sMother;
                        }
                        sw1.WriteLine(sParents);
                        if (sLink != "") sw1.WriteLine("</A>,");
                     }
                     child = null;
                  }

                  if (MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText != "")
                  {
                     sw1.Write(" was born  " + MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText);
                  }
                  if (MyIndividuals[MyFamilies[iFamCount].Wife].BirthPlace != "")
                  {
                     sw1.Write(" in " + FixEstLoc((MyIndividuals[MyFamilies[iFamCount].Wife].BirthPlace)));
                  }
                  sw1.Write(". ");
                  if (MyIndividuals[MyFamilies[iFamCount].Wife].DeathDateText != "" || MyIndividuals[MyFamilies[iFamCount].Wife].DeathPlace != "")
                  {
                     sw1.Write("She died " + MyIndividuals[MyFamilies[iFamCount].Wife].DeathDateText);
                     if (MyIndividuals[MyFamilies[iFamCount].Wife].DeathPlace != "")
                     {
                        sw1.Write(" in " + FixEstLoc((MyIndividuals[MyFamilies[iFamCount].Wife].DeathPlace)));
                     }
                     sw1.WriteLine(". ");
                  }
               }
               sw1.WriteLine("</P>");

               bHasKids = MyFamilies[iFamCount].HasChildren;

               if (bHasKids)
               {
                  iChildCount = 0;
                  sw1.WriteLine("<br>");
                  sw1.Write("Children of ");
                  if (sHusband != "?")
                  {
                     sw1.Write(sHusband);
                     sw1.Write(" and ");
                  }
                  if (sWife != "?")
                  {
                     sw1.Write(sWife);
                  }
                  sw1.WriteLine(" are:");
                  sw1.WriteLine("<br>");

                  //listing children
                  sw1.WriteLine("<table border=" + QUOTE + "0" + QUOTE + " cellpadding=" + QUOTE + "7" + QUOTE + " cellspacing=" + QUOTE + "0" + QUOTE + " width=" + QUOTE + "100%" + QUOTE + ">");
                  foreach (Child child in MyChildren)
                  {
                     if (child.FamilyID == FamRefID)
                     {
                        sLinks = new ArrayList();
                        sLnkFamID = new ArrayList();
                        iNumLinks = 0;
                        //find out if the child has a family page
                        if (MyIndividuals[child.ChildID].Sex == "M" && MyIndividuals[child.ChildID].HasOwnFamily)
                        {
                           if (MyIndividuals[child.ChildID].FamList.Count > 0)
                           {
                              for (iLinkcount = 0; iLinkcount <= MyIndividuals[child.ChildID].FamList.Count - 1; iLinkcount++)
                              {
                                 sLnkFamID.Add(MyIndividuals[child.ChildID].FamList[iLinkcount].FamId);
                                 sLinks.Add(MyIndividuals[child.ChildID].FamList[iLinkcount].FamId);
                                 sLinks[iNumLinks] = sf.Right(sLinks[iNumLinks].ToString(), sf.Len(sLinks[iNumLinks].ToString()) - 2);
                                 sLinks[iNumLinks] = sf.Left(sLinks[iNumLinks].ToString(), sf.Len(sLinks[iNumLinks].ToString()) - 1);
                                 sLinks[iNumLinks] = System.Convert.ToInt32(sLinks[iNumLinks]).ToString("000");
                                 sLinks[iNumLinks] = m_cfg.FamFilePrefix + sLinks[iNumLinks] + ".html";
                                 iNumLinks++;
                              } // iLinkcount
                           }
                        }
                        if (MyIndividuals[child.ChildID].Sex == "F" && MyIndividuals[child.ChildID].HasOwnFamily)
                        {
                           if (MyIndividuals[child.ChildID].FamList.Count > 0)
                           {
                              for (iLinkcount = 0; iLinkcount <= MyIndividuals[child.ChildID].FamList.Count - 1; iLinkcount++)
                              {
                                 sLnkFamID.Add(MyIndividuals[child.ChildID].FamList[iLinkcount].FamId);
                                 sLinks.Add(MyIndividuals[child.ChildID].FamList[iLinkcount].FamId);
                                 sLinks[iNumLinks] = sf.Right(sLinks[iNumLinks].ToString(), sf.Len(sLinks[iNumLinks].ToString()) - 2);
                                 sLinks[iNumLinks] = sf.Left(sLinks[iNumLinks].ToString(), sf.Len(sLinks[iNumLinks].ToString()) - 1);
                                 sLinks[iNumLinks] = System.Convert.ToInt32(sLinks[iNumLinks]).ToString("000");
                                 sLinks[iNumLinks] = m_cfg.FamFilePrefix + sLinks[iNumLinks] + ".html";
                                 iNumLinks++;
                              } // iLinkcount
                           }
                        }

                        iChildCount = iChildCount + 1;
                        sw1.WriteLine("<TR>");
                        sw1.WriteLine("<TD valign=" + QUOTE + "top" + QUOTE + " width=" + QUOTE + "66%" + QUOTE + ">");
                        sw1.Write(sf.Trim(iChildCount.ToString()) + ". " + MyIndividuals[child.ChildID].Forenames + " " + MyIndividuals[child.ChildID].Surname);

                        if (m_cfg.DisplayRIN == true)
                        {
                           sw1.Write("&nbsp;(RIN: " + FixRin(MyIndividuals[child.ChildID].ID) + ")");
                        }
                        if (m_cfg.CreateListReport == true)
                        {
                           sChildName = MyIndividuals[child.ChildID].Forenames + " " + MyIndividuals[child.ChildID].Surname;
                           sw2.WriteLine("{0},{1},{2}", sChildName, MyIndividuals[child.ChildID].ReferenceNumber, sSrnLink);
                        }

                        if (MyIndividuals[child.ChildID].LastChangeDate > dtLastChangeDate) dtLastChangeDate = MyIndividuals[child.ChildID].LastChangeDate;
                        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                        if (m_cfg.CreateGendexFile == true)
                        {
                           //"GENDEX.txt"
                           sGenUrl = sSrnLink;
                           MyGendices.Add(sGenUrl, sf.UCase(MyIndividuals[child.ChildID].Surname), MyIndividuals[child.ChildID].Forenames + " /" + sf.UCase(MyIndividuals[child.ChildID].Surname) + "/", (MyIndividuals[child.ChildID].BirthDateText), (MyIndividuals[child.ChildID].BirthPlace), (MyIndividuals[child.ChildID].DeathDateText), (MyIndividuals[child.ChildID].DeathPlace), CreateGUIDKey());
                        }
                        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


                        if (MyIndividuals[child.ChildID].BirthDateText != "")
                        {
                           sw1.WriteLine(", b. " + MyIndividuals[child.ChildID].BirthDateText);
                        }
                        sw1.WriteLine("</TD>");
                        sw1.WriteLine("<TD valign=" + QUOTE + "top" + QUOTE + " width=" + QUOTE + "33%" + QUOTE + ">");
                        sw1.WriteLine("<FONT SIZE=2><EM>");

                        if (iNumLinks > 0)
                        {

                           for (iLinkcount = 0; iLinkcount <= iNumLinks - 1; iLinkcount++)
                           {
                              if (iLinkcount == 0)
                              {
                                 sw1.WriteLine("See ");
                              }
                              else
                              {
                                 sw1.WriteLine(" OR ");
                              }

                              sw1.WriteLine("<A HREF=" + QUOTE + sLinks[iLinkcount].ToString() + QUOTE + ">");


                              //the husband
                              if (MyFamilies[sLnkFamID[iLinkcount].ToString()].Husband != "?")
                              {
                                 sChHusband = MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Husband].Forenames + " " + MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Husband].Surname;
                                 if (MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Husband].Suffix != "")
                                 {
                                    sChHusband += ", " + MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Husband].Suffix;
                                 }
                              }
                              else
                              {
                                 sChHusband = "?";
                              }

                              //the wife
                              if (MyFamilies[sLnkFamID[iLinkcount].ToString()].Wife != "?")
                              {
                                 sChWife = MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Wife].Forenames + " " + MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Wife].Surname;
                                 if (MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Wife].Suffix != "")
                                 {
                                    sChWife += ", " + MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Wife].Suffix;
                                 }
                              }
                              else
                              {
                                 sChWife = "?";
                              }

                              //title of web page that we are linking to
                              sChTitle = sChHusband + " &amp; " + sChWife;

                              sw1.WriteLine(sChTitle);
                              sw1.WriteLine("</A>");
                           } //
                        }
                        sw1.WriteLine("<FONT>");
                        sw1.WriteLine("</TD>");
                        sw1.WriteLine("</TR>");
                     }
                  } // child
                  sw1.WriteLine("</TABLE>");
               }


               //--------marriage notes
               iNumEvents = MyFamilies[iFamCount].LifeEvents.Count;
               if (iNumEvents > 0 || MyFamilies[iFamCount].Notes != "")
               {
                  bNotesOkay = true;
                  if (MyFamilies[iFamCount].Husband != "?")
                  {
                     if (MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText == Privacy)
                     {
                        bNotesOkay = false;
                     }
                  }
                  if (MyFamilies[iFamCount].Wife != "?")
                  {
                     if (MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText == Privacy)
                     {
                        bNotesOkay = false;
                     }
                  }

                  if (bNotesOkay == true)
                  {

                     sw1.WriteLine("<HR NOSHADE SIZE=1>");
                     bDidLine = true;
                     if (iNumEvents > 0)
                     {
                        sw1.WriteLine("<P><EM>Marriage Events for " + sHusband + "\\" + sWife + ":</EM></P>");
                        sw1.WriteLine("<UL>");
                        foreach (LifeEvent ev in MyFamilies[iFamCount].LifeEvents)
                        {
                           sw1.WriteLine("<LI>");
                           sw1.WriteLine(ev.EventText + "&nbsp; ");
                           sw1.WriteLine(ev.EventDescription + "&nbsp; ");
                           sw1.WriteLine(ev.EventDateString + "&nbsp;");
                           sw1.WriteLine(ev.EventPlace + "&nbsp;");
                           sw1.WriteLine(ev.EventNote + "&nbsp;");
                           sw1.WriteLine("</LI>");
                        } // TheEvent
                        sw1.WriteLine("</UL>");
                     }

                     if (MyFamilies[iFamCount].Notes != "" && m_cfg.ExcludeNotes == false)
                     {
                        //if ( MyIndividuals(MyFamilies[iFamCount].Husband).BirthDateText != Privacy ) {
                        sw1.WriteLine("<P><EM>Marriage Notes for " + sHusband + "\\" + sWife + ":</EM></P>");
                        sw1.WriteLine("<FONT SIZE=2>");
                        foreach (Note note in MyNotes)
                        {
                           if (note.ID == MyFamilies[iFamCount].Notes)
                           {
                              sw1.WriteLine("<p>" + note.NoteText + "</p>");
                           }
                        } // note
                        sw1.WriteLine("</FONT>");
                        //}
                     }

                  }
               }

               //--------------other marriages?
               NumOtherMarriages = 0;
               if (MyFamilies[iFamCount].Husband != "?")
               {
                  aryOtherFams = GetOtherMarriages(MyFamilies[iFamCount].Husband, MyFamilies[iFamCount].ID);
                  if (aryOtherFams.Count != 0)
                  {
                     NumOtherMarriages = aryOtherFams.Count - 1;
                     if (bDidLine == false) sw1.WriteLine("<HR NOSHADE SIZE=1>");
                     sw1.WriteLine("<P><EM>Other Marriages for " + sHusband + ":</EM><BR>");
                     for (iOtherCnt = 0; iOtherCnt <= NumOtherMarriages; iOtherCnt++)
                     {
                        sw1.WriteLine(GetOtherLink(aryOtherFams[iOtherCnt].ToString(), iOtherCnt, false));
                     } // iOtherCnt
                     sw1.WriteLine("</P>");
                  }
               }
               NumOtherMarriages = 0;
               if (MyFamilies[iFamCount].Wife != "?")
               {
                  aryOtherFams = GetOtherMarriages(MyFamilies[iFamCount].Wife, MyFamilies[iFamCount].ID);
                  if (aryOtherFams.Count != 0)
                  {
                     NumOtherMarriages = aryOtherFams.Count - 1;
                     if (bDidLine == false) sw1.WriteLine("<HR NOSHADE SIZE=1>");
                     sw1.WriteLine("<P><EM>Other Marriages for " + sWife + ":</EM><BR>");
                     for (iOtherCnt = 0; iOtherCnt <= NumOtherMarriages; iOtherCnt++)
                     {
                        sw1.WriteLine(GetOtherLink(aryOtherFams[iOtherCnt].ToString(), iOtherCnt, false));
                     } // iOtherCnt
                     sw1.WriteLine("</P>");
                  }
               }
               bDidLine = false;

               //now the notes
               if (sHusband != "?")
               {

                  iNumEvents = MyIndividuals[MyFamilies[iFamCount].Husband].LifeEvents.Count;
                  bDidLine = false;

                  if (iNumEvents > 0 || MyIndividuals[MyFamilies[iFamCount].Husband].Notes != "")
                  {
                     if (MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText != Privacy)
                     {
                        sw1.WriteLine("<HR NOSHADE SIZE=1>");
                        bDidLine = true;
                        sw1.WriteLine("<P><EM>Notes for " + sHusband + ":</EM></P>");
                     }
                  }

                  if (MyIndividuals[MyFamilies[iFamCount].Husband].AliasName != "")
                  {
                     if (MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText != Privacy)
                     {
                        sw1.WriteLine("Also known as: " + MyIndividuals[MyFamilies[iFamCount].Husband].AliasName);
                     }
                  }

                  if (iNumEvents > 0)
                  {
                     if (MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText != Privacy)
                     {
                        sw1.WriteLine("<UL>");
                        foreach (LifeEvent ev in MyIndividuals[MyFamilies[iFamCount].Husband].LifeEvents)
                        {
                           sw1.WriteLine("<LI>");
                           sw1.WriteLine(ev.EventText + "&nbsp; ");
                           sw1.WriteLine(ev.EventDescription + "&nbsp; ");
                           sw1.WriteLine(ev.EventDateString + "&nbsp;");
                           sw1.WriteLine(ev.EventPlace + "&nbsp;");
                           sw1.WriteLine(ev.EventNote + "&nbsp;");
                           sw1.WriteLine("</LI>");
                        } // ev
                        if (MyIndividuals[MyFamilies[iFamCount].Husband].Nationality != "")
                        {
                           sw1.WriteLine("<LI>");
                           sw1.WriteLine("Nationality " + MyIndividuals[MyFamilies[iFamCount].Husband].Nationality);
                           sw1.WriteLine("</LI>");
                        }
                        sw1.WriteLine("</UL>");
                     }
                  }

                  if (MyIndividuals[MyFamilies[iFamCount].Husband].Notes != "" && m_cfg.ExcludeNotes == false)
                  {
                     if (MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText != Privacy)
                     {
                        sw1.WriteLine("<FONT SIZE=2>");
                        foreach (Note note in MyNotes)
                        {
                           if (note.ID == MyIndividuals[MyFamilies[iFamCount].Husband].Notes)
                           {
                              sw1.WriteLine("<p>" + note.NoteText + "</p>");
                           }
                        } // note
                        sw1.WriteLine("</FONT>");
                     }
                  }

                  //sources for husband
                  iNumSrcs = MyIndividuals[MyFamilies[iFamCount].Husband].Sources.Count;

                  if (iNumSrcs > 0)
                  {
                     if (bDidLine == false) sw1.WriteLine("<HR NOSHADE SIZE=1>");
                     sw1.WriteLine("<P><EM>Sources for " + sHusband + ":</EM></P>");
                  }


                  if (iNumSrcs > 0)
                  {
                     sw1.WriteLine("<FONT SIZE=2>");
                     sw1.WriteLine("<OL>");
                     foreach (Source src in MyIndividuals[MyFamilies[iFamCount].Husband].Sources)
                     {
                        sw1.Write("<LI>");
                        if (m_cfg.FamFilePrefix == "fam")
                        {
                           sw1.Write("<EM>" + "<a href=" + QUOTE + "sources.html#" + src.ID + QUOTE + " target=" + QUOTE + _srcTarget + QUOTE + ">" + MySources[src.ID].Title + "</a>, " + "</EM>" + src.Page);
                        }
                        else
                        {
                           sw1.Write("<EM>" + "<a href=" + QUOTE + m_cfg.FamFilePrefix + "_sources.html#" + src.ID + QUOTE + " target=" + QUOTE + _srcTarget + QUOTE + ">" + MySources[src.ID].Title + "</a>, " + "</EM>" + src.Page);
                        }
                        if (src.Note != "")
                        {
                           sw1.Write(" Note: " + src.Note + "&nbsp;");
                        }
                        if (src.SourceText != "")
                        {
                           sw1.Write("<em>" + src.SourceText + "</em>");
                        }
                        sw1.WriteLine("</LI>");
                     } // src
                     sw1.WriteLine("</OL>");
                     sw1.WriteLine("</FONT>");
                  }

               }

               //*************NOTES FOR WIFE
               if (sWife != "?")
               {

                  iNumEvents = MyIndividuals[MyFamilies[iFamCount].Wife].LifeEvents.Count;
                  bDidLine = false;

                  if (iNumEvents > 0 || MyIndividuals[MyFamilies[iFamCount].Wife].Notes != "")
                  {
                     if (MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText != Privacy)
                     {
                        sw1.WriteLine("<HR NOSHADE SIZE=1>");
                        bDidLine = true;
                        sw1.WriteLine("<P><EM>Notes for " + sWife + ":</EM></P>");
                     }
                  }

                  if (MyIndividuals[MyFamilies[iFamCount].Wife].AliasName != "")
                  {
                     if (MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText != Privacy)
                     {
                        sw1.WriteLine("Also known as: " + MyIndividuals[MyFamilies[iFamCount].Wife].AliasName);
                     }
                  }

                  if (iNumEvents > 0)
                  {
                     if (MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText != Privacy)
                     {
                        sw1.WriteLine("<UL>");
                        foreach (LifeEvent ev in MyIndividuals[MyFamilies[iFamCount].Wife].LifeEvents)
                        {
                           sw1.WriteLine("<LI>");
                           sw1.WriteLine(ev.EventText + "&nbsp; ");
                           sw1.WriteLine(ev.EventDescription + "&nbsp; ");
                           sw1.WriteLine(ev.EventDateString + "&nbsp;");
                           sw1.WriteLine(ev.EventPlace + "&nbsp;");
                           sw1.WriteLine(ev.EventNote + "&nbsp;");
                           sw1.WriteLine("</LI>");
                        } // ev
                        if (MyIndividuals[MyFamilies[iFamCount].Wife].Nationality != "")
                        {
                           sw1.WriteLine("<LI>");
                           sw1.WriteLine("Nationality " + MyIndividuals[MyFamilies[iFamCount].Wife].Nationality);
                           sw1.WriteLine("</LI>");
                        }
                        sw1.WriteLine("</UL>");
                     }
                  }

                  if (MyIndividuals[MyFamilies[iFamCount].Wife].Notes != "" && m_cfg.ExcludeNotes == false)
                  {
                     if (MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText != Privacy)
                     {
                        sw1.WriteLine("<FONT SIZE=2>");
                        foreach (Note note in MyNotes)
                        {
                           if (note.ID == MyIndividuals[MyFamilies[iFamCount].Wife].Notes)
                           {
                              sw1.WriteLine("<p>" + note.NoteText + "</p>");
                           }
                        } // note
                        sw1.WriteLine("</FONT>");
                     }
                  }

                  //sources for wife
                  iNumSrcs = MyIndividuals[MyFamilies[iFamCount].Wife].Sources.Count;

                  if (iNumSrcs > 0)
                  {
                     if (bDidLine == false) sw1.WriteLine("<HR NOSHADE SIZE=1>");
                     sw1.WriteLine("<P><EM>Sources for " + sWife + ":</EM></P>");
                  }


                  if (iNumSrcs > 0)
                  {
                     sw1.WriteLine("<FONT SIZE=2>");
                     sw1.WriteLine("<OL>");
                     foreach (Source src in MyIndividuals[MyFamilies[iFamCount].Wife].Sources)
                     {
                        sw1.Write("<LI>");
                        if (m_cfg.FamFilePrefix == "fam")
                        {
                           sw1.Write("<EM>" + "<a href=" + QUOTE + "sources.html#" + src.ID + QUOTE + " target=" + QUOTE + _srcTarget + QUOTE + ">" + MySources[src.ID].Title + "</a>, " + "</EM>" + src.Page);
                        }
                        else
                        {
                           sw1.Write("<EM>" + "<a href=" + QUOTE + m_cfg.FamFilePrefix + "_sources.html#" + src.ID + QUOTE + " target=" + QUOTE + _srcTarget + QUOTE + ">" + MySources[src.ID].Title + "</a>, " + "</EM>" + src.Page);
                        }
                        if (src.Note != "")
                        {
                           sw1.Write(" Note: " + src.Note);
                        }
                        if (src.SourceText != "")
                        {
                           sw1.Write("<em>" + src.SourceText + "</em>");
                        }
                        sw1.WriteLine("</LI>");
                     } // src
                     sw1.WriteLine("</OL>");
                     sw1.WriteLine("</FONT>");
                  }
               }

               //------------print notes for children without family records
               foreach (Child child in MyChildren)
               {
                  if (child.FamilyID == FamRefID)
                  {

                     if (MyIndividuals[child.ChildID].HasOwnFamily == false)
                     {
                        //print the child//s notes on this page (this change decreased proc time by 30%)
                        iNumEvents = MyIndividuals[child.ChildID].LifeEvents.Count;

                        bDoNotes = false;
                        if (iNumEvents > 0) bDoNotes = true;
                        if (MyIndividuals[child.ChildID].Notes != "") bDoNotes = true;
                        if (MyIndividuals[child.ChildID].BirthDateText != "") bDoNotes = true;
                        if (MyIndividuals[child.ChildID].BirthDateText == Privacy) bDoNotes = false;

                        bDidLine = false;
                        //if we can print notes then print the notes
                        if (bDoNotes)
                        {
                           sw1.WriteLine("<HR NOSHADE SIZE=1>");
                           bDidLine = true;
                           sw1.WriteLine("<P><EM>Notes for " + MyIndividuals[child.ChildID].Forenames + " " + MyIndividuals[child.ChildID].Surname + ":</EM></P>");

                           if (MyIndividuals[child.ChildID].AliasName != "")
                           {
                              if (MyIndividuals[child.ChildID].BirthDateText != Privacy)
                              {
                                 sw1.WriteLine("Also known as: " + MyIndividuals[child.ChildID].AliasName);
                              }
                           }

                           sw1.WriteLine("<UL>");
                           if (MyIndividuals[child.ChildID].BirthDateText != "")
                           {
                              if (sf.IsDate(MyIndividuals[child.ChildID].BirthDateText))
                              {
                                 sw1.Write("<LI>Born  " + sf.DateValue(MyIndividuals[child.ChildID].BirthDateText).ToString("MMMM dd,yyyy"));
                              }
                              else
                              {
                                 sw1.Write("<LI>Born  " + MyIndividuals[child.ChildID].BirthDateText);
                              }
                           }
                           if (MyIndividuals[child.ChildID].BirthPlace != "")
                           {
                              sw1.Write(" in " + FixEstLoc((MyIndividuals[child.ChildID].BirthPlace)));
                              sw1.WriteLine(". </LI>");
                           }
                           else
                           {
                              sw1.WriteLine(". </LI>");
                           }

                           if (MyIndividuals[child.ChildID].DeathDateText != "" || MyIndividuals[child.ChildID].DeathPlace != "")
                           {
                              sw1.Write("<LI>Died " + MyIndividuals[child.ChildID].DeathDateText);
                              if (MyIndividuals[child.ChildID].DeathPlace != "")
                              {
                                 sw1.WriteLine(" in " + FixEstLoc((MyIndividuals[child.ChildID].DeathPlace)) + "</LI>");
                              }
                              sw1.WriteLine(". </LI>");
                           }

                           if (iNumEvents > 0)
                           {
                              if (MyIndividuals[child.ChildID].BirthDateText != Privacy)
                              {
                                 foreach (LifeEvent TheEvent in MyIndividuals[child.ChildID].LifeEvents)
                                 {
                                    //allow birth and death are recorded as events
                                    //they are handled separately (see above)
                                    if (TheEvent.EventText != "Birth" && TheEvent.EventText != "Death")
                                    {
                                       sw1.WriteLine("<LI>");
                                       sw1.WriteLine(TheEvent.EventText + "&nbsp; ");
                                       sw1.WriteLine(TheEvent.EventDescription + "&nbsp; ");
                                       sw1.WriteLine(TheEvent.EventDateString + "&nbsp;");
                                       sw1.WriteLine(TheEvent.EventPlace + "&nbsp;");
                                       sw1.WriteLine(TheEvent.EventNote + "&nbsp;");
                                       sw1.WriteLine("</LI>");
                                    }
                                 } // TheEvent

                                 if (MyIndividuals[child.ChildID].Nationality != "")
                                 {
                                    sw1.WriteLine("<LI>");
                                    sw1.WriteLine("Nationality " + MyIndividuals[child.ChildID].Nationality);
                                    sw1.WriteLine("</LI>");
                                 }
                              }
                           }
                           sw1.WriteLine("</UL>");

                           if (MyIndividuals[child.ChildID].Notes != "" && m_cfg.ExcludeNotes == false)
                           {
                              if (MyIndividuals[child.ChildID].BirthDateText != Privacy)
                              {
                                 sw1.WriteLine("<FONT SIZE=2>");
                                 foreach (Note note in MyNotes)
                                 {
                                    if (note.ID == MyIndividuals[child.ChildID].Notes)
                                    {
                                       sw1.WriteLine("<p>" + note.NoteText + "</p>");
                                    }
                                 } // note
                                 sw1.WriteLine("</FONT>");
                              }
                           }
                        } //end of notes

                        //**********how about sources for this child?
                        //**********added ver 3.01
                        iNumSrcs = MyIndividuals[child.ChildID].Sources.Count;

                        if (iNumSrcs > 0)
                        {
                           if (bDidLine == false) sw1.WriteLine("<HR NOSHADE SIZE=1>");
                           sw1.WriteLine("<P><EM>Sources for " + MyIndividuals[child.ChildID].Forenames + " " + MyIndividuals[child.ChildID].Surname + ":</EM></P>");
                        }


                        if (iNumSrcs > 0)
                        {
                           sw1.WriteLine("<FONT SIZE=2>");
                           sw1.WriteLine("<OL>");
                           foreach (Source TheSource in MyIndividuals[child.ChildID].Sources)
                           {
                              sw1.Write("<LI>");
                              if (m_cfg.FamFilePrefix == "fam")
                              {
                                 sw1.Write("<EM>" + "<a href=" + QUOTE + "sources.html#" + TheSource.ID + QUOTE + " target=" + QUOTE + _srcTarget + QUOTE + ">" + MySources[TheSource.ID].Title + "</a>, " + "</EM>" + TheSource.Page);
                              }
                              else
                              {
                                 sw1.Write("<EM>" + "<a href=" + QUOTE + m_cfg.FamFilePrefix + "_sources.html#" + TheSource.ID + QUOTE + " target=" + QUOTE + _srcTarget + QUOTE + ">" + MySources[TheSource.ID].Title + "</a>, " + "</EM>" + TheSource.Page);
                              }
                              if (TheSource.Note != "")
                              {
                                 sw1.Write(" Note: " + TheSource.Note);
                              }
                              if (TheSource.SourceText != "")
                              {
                                 sw1.Write("<em>" + TheSource.SourceText + "</em>");
                              }
                              sw1.WriteLine("</LI>");
                           } // TheSource
                           sw1.WriteLine("</OL>");
                           sw1.WriteLine("</FONT>");
                        }
                        //********************end of sources for child
                     }
                  }
               } // child

               if (dtLastChangeDate > System.DateTime.FromOADate(0) && m_cfg.MostRecentOnPage == true)
               {
                  sw1.WriteLine("<HR NOSHADE SIZE=1>");
                  sw1.WriteLine("<p><center><em>The most recent update of information contained on this page was on:</em>&nbsp;" + dtLastChangeDate.ToString("dd MMMM yyyy") + "</center></p>");
               }
               sw1.WriteLine("<HR NOSHADE SIZE=1>");
               sw1.WriteLine("<EM><CENTER>");
               if (m_cfg.FamFilePrefix == "fam")
               {
                  sw1.WriteLine("<A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">");
               }
               else
               {
                  sw1.WriteLine("<A HREF=" + QUOTE + m_cfg.FamFilePrefix + "_ind_idx.html" + QUOTE + ">");
               }
               sw1.WriteLine("Index");
               sw1.WriteLine("</A>");
               sw1.WriteLine("</CENTER></EM>");
               sw1.WriteLine("<EM><CENTER>");
               if (m_cfg.FamFilePrefix == "fam")
               {
                  sw1.WriteLine("<A HREF=" + QUOTE + "surnames.html" + QUOTE + ">");
               }
               else
               {
                  sw1.WriteLine("<A HREF=" + QUOTE + m_cfg.FamFilePrefix + "_surnames.html" + QUOTE + ">");
               }
               sw1.WriteLine("Surnames");
               sw1.WriteLine("</A>");
               sw1.WriteLine("</CENTER></EM>");
               sw1.WriteLine("<EM><CENTER>");
               sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
               sw1.WriteLine("Table Of Contents");
               sw1.WriteLine("</A>");

               sw1.WriteLine("</CENTER></EM>");
               sw1.WriteLine("<HR NOSHADE SIZE=1>");

               if (m_cfg.AddUserCopyright == true && m_cfg.AuthorsName != "")
               {
                  sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
                  sw1.Write("Copyright &copy; " + DateTime.Now.Year.ToString() + "&nbsp;");
                  if (m_cfg.AuthorsEmail != "") sw1.Write("<A href=" + QUOTE + "mailto:" + m_cfg.AuthorsEmail + QUOTE + ">");
                  sw1.Write(m_cfg.AuthorsName);
                  if (m_cfg.AuthorsEmail != "") sw1.Write("</A>");
                  sw1.WriteLine("</CENTER></P></FONT>");
               }

               sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
               sw1.WriteLine("This page was created on " + DateTime.Now.ToShortDateString() + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
               sw1.WriteLine("Copyright &copy; 1999-2007 D. M. DeBacker");
               sw1.WriteLine("</CENTER></P></FONT>");

               sw1.WriteLine("</BODY>");
               sw1.WriteLine("</HTML>");

               sw1.Close();
               fs1.Close();
            } // iFamCount

            if (m_cfg.CreateListReport == true)
            {
               sw2.Close();
               fs2.Close();
            }

            return true;

         BUILDFAMILY_EXIT:
            sw1.Close();
            fs1.Close();
            if (m_cfg.CreateListReport == true)
            {
               sw2.Close();
               fs2.Close();
            }

            return true;

         }
         catch (Exception ex)
         {

            FireStatusMessage("The following error occured in BuildFamilyPages while processing the GEDCOM file:" + '\n' + '\r' + "Error: " + ex.Message);
            FireStatusMessage("Incomplete");

            try
            {
               sw1.Close();
               fs1.Close();
               if (m_cfg.CreateListReport == true)
               {
                  sw2.Close();
                  fs2.Close();
               }
               return false;
            }
            catch { return false; }
         }

      }


      /// <summary>
      /// Summary of BuildIndexEach.
      /// </summary>
      /// 		
      private void BuildIndexEach()
      {
         string sFile;
         int iIndCount;
         int iNumInds;
         ArrayList sLinks = new ArrayList();
         string sLink;
         string sFullName;
         string sCurrChar;
         string sPrevChar;
         string sUpdate;
         DateTime DaysAgo90;
         FileStream fs1;
         StreamWriter sw1;

         iNumInds = MyIndividuals.Count;
         sLinks.Capacity = iNumInds + 1;

         for (iIndCount = 0; iIndCount <= iNumInds - 1; iIndCount++)
         {
            sLinks.Add("");
         }

         SortedList sl = new SortedList(iNumInds);

         char QUOTE = '"';

         DaysAgo90 = DateTime.Now.AddDays(-90);

         if (iNumInds == 0) return;

         sl.Clear();

         iIndCount = 0;
         foreach (Individual individual in MyIndividuals)
         {
            sFullName = sf.UCase(individual.Surname) + ", " + individual.Forenames;
            if (individual.Suffix != "")
            {
               sFullName = sFullName + ", " + individual.Suffix;
            }

            sFullName = sFullName + "</A></td><td width=" + QUOTE + "30%" + QUOTE + ">";

            if (individual.BirthDateText != "" && individual.BirthDateText != Privacy)
            {
               sFullName = sFullName + individual.BirthDateText;
            }

            sFullName = sFullName + "</td><td width=" + QUOTE + "30%" + QUOTE + ">";

            if (individual.LastChangeDate != System.DateTime.FromOADate(0) && m_cfg.MostRecentOnIndex == true)
            {
               sUpdate = "";
               if (m_cfg.HiLiteMostRecent && individual.LastChangeDate > DaysAgo90)
               {
                  sUpdate = "<b>";
               }
               sUpdate = sUpdate + individual.LastChangeDate.ToString("dd MMM yyyy");
               if (m_cfg.HiLiteMostRecent && individual.LastChangeDate > DaysAgo90)
               {
                  sUpdate = sUpdate + "</b>";
               }
               sFullName = sFullName + sUpdate;
            }

            sFullName = sFullName + "</td>";

            //find out which family page they go own
            //==========4.00.4097 optimization
            if (individual.HasOwnFamily == true)
            {
               if (individual.FamList[0].FamId.Length != 0)
               {

                  sLinks[iIndCount] = individual.FamList[0].FamId;
                  sLinks[iIndCount] = sf.Right(sLinks[iIndCount].ToString(), sf.Len(sLinks[iIndCount].ToString()) - 2);
                  int iLinkNumber = System.Convert.ToInt32(sf.Left(sLinks[iIndCount].ToString(), sf.Len(sLinks[iIndCount].ToString()) - 1));
                  sLinks[iIndCount] = iLinkNumber.ToString("000");
                  sLinks[iIndCount] = m_cfg.FamFilePrefix + sLinks[iIndCount].ToString() + ".html";
                  if (sLinks[iIndCount].ToString() != "")
                  {
                     sl.Add(sFullName + CreateGUIDKey(), iIndCount);
                     individual.LinkPage = sLinks[iIndCount].ToString();
                  }
               }
            }
            else
            {
               if (individual.FamilyID.Length != 0)
               {
                  sLinks[iIndCount] = individual.FamilyID;
                  sLinks[iIndCount] = sf.Right(sLinks[iIndCount].ToString(), sf.Len(sLinks[iIndCount].ToString()) - 2);
                  int iLinkNumber = System.Convert.ToInt32(sf.Left(sLinks[iIndCount].ToString(), sf.Len(sLinks[iIndCount].ToString()) - 1));
                  sLinks[iIndCount] = iLinkNumber.ToString("000");
                  sLinks[iIndCount] = m_cfg.FamFilePrefix + sLinks[iIndCount].ToString() + ".html";
                  if (sLinks[iIndCount].ToString() != "")
                  {
                     sl.Add(sFullName + CreateGUIDKey(), iIndCount);
                     individual.LinkPage = sLinks[iIndCount].ToString();
                  }
               }
            }
            iIndCount++;
         } // individual

         if (m_cfg.FamFilePrefix == "fam")
         {
            sFile = m_cfg.HtmlPath + "\\ind_idx.html";
         }
         else
         {
            sFile = m_cfg.HtmlPath + "\\" + m_cfg.FamFilePrefix + "_ind_idx.html";
         }

         fs1 = new FileStream(sFile, FileMode.Create);
         sw1 = new StreamWriter(fs1);

         //file header
         sw1.WriteLine("<HTML>");
         sw1.WriteLine("<HEAD>");
         if (m_cfg.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
         sw1.WriteLine("<TITLE>Index Of Individuals</TITLE>");
         sw1.WriteLine("<META NAME=" + QUOTE + " Generator" + QUOTE + " CONTENT=" + QUOTE + " UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");
         sw1.WriteLine("</HEAD>");
         if (m_cfg.UseBackground)
         {
            sw1.WriteLine("<body background=" + QUOTE + m_cfg.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         sw1.WriteLine("<p><a name=" + QUOTE + "TOP" + QUOTE + ">&nbsp;</a></p>");
         if (m_cfg.UseBanner)
         {
            sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + m_cfg.BannerFile + QUOTE + "></p>");
         }
         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<CENTER>");
         sw1.WriteLine("<a href=" + QUOTE + "#A" + QUOTE + ">A</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#B" + QUOTE + ">B</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#C" + QUOTE + ">C</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#D" + QUOTE + ">D</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#E" + QUOTE + ">E</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#F" + QUOTE + ">F</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#G" + QUOTE + ">G</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#H" + QUOTE + ">H</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#I" + QUOTE + ">I</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#J" + QUOTE + ">J</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#K" + QUOTE + ">K</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#L" + QUOTE + ">L</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#M" + QUOTE + ">M</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#N" + QUOTE + ">N</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#O" + QUOTE + ">O</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#P" + QUOTE + ">P</a>&nbsp;");

         sw1.WriteLine("<a href=" + QUOTE + "#Q" + QUOTE + ">Q</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#R" + QUOTE + ">R</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#S" + QUOTE + ">S</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#T" + QUOTE + ">T</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#U" + QUOTE + ">U</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#V" + QUOTE + ">V</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#W" + QUOTE + ">W</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#X" + QUOTE + ">X</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#Y" + QUOTE + ">Y</a>&nbsp;");
         sw1.WriteLine("<a href=" + QUOTE + "#Z" + QUOTE + ">Z</a>&nbsp;");
         sw1.WriteLine("</CENTER>");
         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sPrevChar = "#";
         for (iIndCount = 0; iIndCount <= iNumInds - 1; iIndCount++)
         {
            if (_didCancel) return;
            if (iIndCount < sl.Count)
            {
               sFullName = sf.Left((string)sl.GetKey(iIndCount), sf.Len((string)sl.GetKey(iIndCount)) - 36); //strip off GUID;
            }
            else
            {
               sFullName = "";
            }

            if (sFullName != "")
            {
               sLink = sLinks[(int)sl.GetByIndex(iIndCount)].ToString();
               sCurrChar = sf.UCase(sf.Left(sf.Trim(sFullName), 1));
               if (sPrevChar != sCurrChar)
               {
                  if (System.Convert.ToChar(sCurrChar) >= 'A')
                  {
                     sw1.WriteLine("</TABLE>");//end the previous table;
                     sw1.WriteLine("<EM><CENTER>" + "<A HREF=" + QUOTE + "#TOP" + QUOTE + ">" + "Top</A></CENTER></EM>");
                     sw1.WriteLine("<HR NOSHADE SIZE=1>");
                  }
                  sw1.WriteLine("<H2><A NAME=" + QUOTE + sCurrChar + QUOTE + ">");
                  sw1.WriteLine(sCurrChar);
                  sw1.WriteLine("</A></H2><BR>");
                  sPrevChar = sCurrChar;
                  //start a new table
                  sw1.WriteLine("<table border=" + QUOTE + "0" + QUOTE + " cellpadding=" + QUOTE + "1" + QUOTE + " cellspacing=" + QUOTE + "1" + QUOTE + " width=" + QUOTE + "100%" + QUOTE + " > ");

                  if (m_cfg.MostRecentOnIndex == true)
                  {
                     sw1.WriteLine("<tr><th width=" + QUOTE + "40%" + QUOTE + "><em>Name</em></td><th width=" + QUOTE + "30%" + QUOTE + "><em>Date Of Birth</em></td><th width=" + QUOTE + "30%" + QUOTE + "><em>Last Updated</em></td><tr>");
                  }
                  else
                  {
                     sw1.WriteLine("<tr><th width=" + QUOTE + "40%" + QUOTE + "><em>Name</em></td><th width=" + QUOTE + "30%" + QUOTE + "><em>Date Of Birth</em></td><tr>");
                  }
               }
               sw1.Write("<tr><td width=" + QUOTE + "40%" + QUOTE + "><A HREF=" + QUOTE + sLink + QUOTE + ">");
               sw1.Write(sFullName);
               sw1.WriteLine("</TR>");
            }
         } // iIndCount

         sw1.WriteLine("</TABLE>");//end the last table;
         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<EM><CENTER>" + "<A HREF=" + QUOTE + "#TOP" + QUOTE + ">" + "Top</A></CENTER></EM>");
         sw1.WriteLine("<EM><CENTER>");
         if (m_cfg.FamFilePrefix == "fam")
         {
            sw1.WriteLine("<A HREF=" + QUOTE + "surnames.html" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<A HREF=" + QUOTE + m_cfg.FamFilePrefix + "_surnames.html" + QUOTE + ">");
         }
         sw1.WriteLine("Surnames");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<EM><CENTER>");
         sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
         sw1.WriteLine("Table Of Contents");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<HR NOSHADE SIZE=1>");

         if (m_cfg.AddUserCopyright == true && m_cfg.AuthorsName != "")
         {
            sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
            sw1.Write("Copyright &copy; " + DateTime.Now.Year.ToString("yyyy") + "&nbsp;");
            if (m_cfg.AuthorsEmail != "") sw1.Write("<A href=" + QUOTE + "mailto:" + m_cfg.AuthorsEmail + QUOTE + ">");
            sw1.Write(m_cfg.AuthorsName);
            if (m_cfg.AuthorsEmail != "") sw1.Write("</A>");
            sw1.WriteLine("</CENTER></P></FONT>");
         }

         sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
         sw1.WriteLine("This page was created on " + DateTime.Now.ToString("MM/dd/yy") + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
         sw1.WriteLine("Copyright &copy; 1999-2007 D. M. DeBacker");
         sw1.WriteLine("</CENTER></P></FONT>");
         sw1.WriteLine("</BODY>");
         sw1.WriteLine("</HTML>");

         sw1.Close();
         fs1.Close();
      }


      /// <summary>
      /// Summary of BuildBiblio.
      /// </summary>
      /// 		
      private void BuildBiblio()
      {
         string sFile;
         int cnt;
         int iNumSrcs;
         FileStream fs1;
         StreamWriter sw1;

         //MainForm.pbFile.value = 0

         iNumSrcs = MySources.Count;

         char QUOTE = '"';

         if (iNumSrcs == 0) return;

         //lFn = FreeFile()

         if (m_cfg.FamFilePrefix == "fam")
         {
            sFile = m_cfg.HtmlPath + "\\sources.html";
         }
         else
         {
            sFile = m_cfg.HtmlPath + "\\" + m_cfg.FamFilePrefix + "_sources.html";
         }

         fs1 = new FileStream(sFile, FileMode.Create);
         sw1 = new StreamWriter(fs1);

         //file header
         sw1.WriteLine("<HTML>");
         sw1.WriteLine("<HEAD>");
         if (m_cfg.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
         sw1.WriteLine("<TITLE>Bibliography</TITLE>");
         sw1.WriteLine("<META NAME=" + QUOTE + " Generator" + QUOTE + " CONTENT=" + QUOTE + " UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");
         sw1.WriteLine("</HEAD>");
         if (m_cfg.UseBackground)
         {
            sw1.WriteLine("<body background=" + QUOTE + m_cfg.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         sw1.WriteLine("<p><a name=" + QUOTE + "TOP" + QUOTE + ">&nbsp;</a></p>");
         if (m_cfg.UseBanner)
         {
            sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + m_cfg.BannerFile + QUOTE + "></p>");
         }
         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<CENTER>");
         sw1.WriteLine("<H1>Bibliography</H1>");
         sw1.WriteLine("</CENTER>");
         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<OL>");

         for (cnt = 0; cnt <= iNumSrcs - 1; cnt++)
         {
            if (_didCancel) goto BUILDBIBLIO_EXIT;
            if (MySources[cnt].Author != "")
            {
               sw1.Write("<LI>" + MySources[cnt].Author + ",&nbsp;<EM>");
            }
            else
            {
               sw1.Write("<LI>");
            }

            sw1.Write("<a name=" + MySources[cnt].ID + ">" + MySources[cnt].Title + "</a>");

            if (MySources[cnt].Author != "")
            {
               sw1.Write("</EM>");
            }

            if (MySources[cnt].PublicationInfo != "")
            {
               sw1.Write(",&nbsp;" + MySources[cnt].PublicationInfo);
            }
            if (MySources[cnt].Media != "")
            {
               sw1.Write(",&nbsp;[" + MySources[cnt].Media + "]");
            }
            if (MySources[cnt].Note != "")
            {
               sw1.Write("&nbsp;<font size=2>(" + MySources[cnt].Note + ")</font>");
            }
            sw1.WriteLine("<br></LI>");
         } // iSrcCount

         sw1.WriteLine("</OL>");

         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<EM><CENTER>");
         if (m_cfg.FamFilePrefix == "fam")
         {
            sw1.WriteLine("<A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<A HREF=" + QUOTE + m_cfg.FamFilePrefix + "_ind_idx.html" + QUOTE + ">");
         }
         sw1.WriteLine("Index");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<EM><CENTER>");
         sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
         sw1.WriteLine("Table Of Contents");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<HR NOSHADE SIZE=1>");

         if (m_cfg.AddUserCopyright == true && m_cfg.AuthorsName != "")
         {
            sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
            sw1.Write("Copyright &copy; " + DateTime.Now.ToString("yyyy") + "&nbsp;");
            if (m_cfg.AuthorsEmail != "") sw1.Write("<A href=" + QUOTE + "mailto:" + m_cfg.AuthorsEmail + QUOTE + ">");
            sw1.Write(m_cfg.AuthorsName);
            if (m_cfg.AuthorsEmail != "") sw1.Write("</A>");
            sw1.WriteLine("</CENTER></P></FONT>");
         }

         sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
         sw1.WriteLine("This page was created on " + DateTime.Now.ToString("MM/dd/yy") + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
         sw1.WriteLine("Copyright &copy; 1999-2007 D. M. DeBacker");
         sw1.WriteLine("</CENTER></P></FONT>");
         sw1.WriteLine("</BODY>");
         sw1.WriteLine("</HTML>");

      BUILDBIBLIO_EXIT: ;
         sw1.Close();
         fs1.Close();
      }


      /// <summary>
      /// Summary of BuildSurnamePage.
      /// </summary>
      /// 		
      private void BuildSurnamePage()
      {
         string sFile;
         int iSrnCount;
         int iNumSrns;
         string sLink;
         string sFamilyName;
         string sItemCnt;
         ArrayList sLinks = new ArrayList();
         ArrayList iSrnCnt = new ArrayList();
         FileStream fs1;
         StreamWriter sw1;
         Surname NewSurname;

         //moved here in 0.7 count all of the surnames
         for (int i = 0; i <= MyIndividuals.Count - 1; i++)
         {
            NewSurname = new Surname();
            NewSurname.FamilyName = sf.UCase(MyIndividuals[i].Surname);
            NewSurname.FirstLink = MyIndividuals[i].LinkPage;
            if (MySurnames.Add(NewSurname) == false)
            {
               //if it failed to add then increment it
               MySurnames[NewSurname.FamilyName].NumItems = MySurnames[NewSurname.FamilyName].NumItems + 1;
            }
            NewSurname = null;
         }

         iNumSrns = MySurnames.Count;

         char QUOTE = '"';

         if (iNumSrns == 0) return;

         SortedList sl = new SortedList(iNumSrns);

         //put in sorted list for quick and dirty sort
         sl.Clear();

         for (iSrnCount = 0; iSrnCount <= iNumSrns - 1; iSrnCount++)
         {
            sl.Add(MySurnames[iSrnCount].FamilyName + CreateGUIDKey(), iSrnCount);
            sLinks.Add(MySurnames[iSrnCount].FirstLink);
            iSrnCnt.Add(MySurnames[iSrnCount].NumItems);
         } // iSrnCount


         if (m_cfg.FamFilePrefix == "fam")
         {
            sFile = m_cfg.HtmlPath + "\\surnames.html";
         }
         else
         {
            sFile = m_cfg.HtmlPath + "\\" + m_cfg.FamFilePrefix + "_surnames.html";
         }

         fs1 = new FileStream(sFile, FileMode.Create);
         sw1 = new StreamWriter(fs1);

         //file header
         sw1.WriteLine("<HTML>");
         sw1.WriteLine("<HEAD>");
         if (m_cfg.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
         sw1.WriteLine("<TITLE>Surnames</TITLE>");
         sw1.WriteLine("<META NAME=" + QUOTE + "Generator" + QUOTE + " CONTENT=" + QUOTE + "UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");
         sw1.WriteLine("</HEAD>");
         if (m_cfg.UseBackground)
         {
            sw1.WriteLine("<body background=" + QUOTE + m_cfg.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         sw1.WriteLine("<p><a name=" + QUOTE + "TOP" + QUOTE + ">&nbsp;</a></p>");
         if (m_cfg.UseBanner)
         {
            sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + m_cfg.BannerFile + QUOTE + "></p>");
         }
         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<CENTER>");
         sw1.WriteLine("<H1>Surnames</H1>");
         sw1.WriteLine("</CENTER>");
         sw1.WriteLine("<EM><CENTER>");
         sw1.WriteLine("<FONT SIZE=2>");
         sw1.Write("The database is arranged in ascending order, beginning with the primary individual and branching out towards ");
         sw1.Write("the ancestors of the primary individual. The surname links follow this pattern such that selecting a surname will ");
         sw1.Write("take you to the first appearance of that surname on the branch leading from the primary individual. This does not mean ");
         sw1.Write("that this is the only appearance of this surname and it is suggested that you follow links within the database or make use ");
         sw1.WriteLine("of the index for finding more details.");
         sw1.WriteLine("</FONT>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<OL>");

         for (iSrnCount = 0; iSrnCount <= iNumSrns - 1; iSrnCount++)
         {
            sFamilyName = sf.Left((string)sl.GetKey(iSrnCount), sf.Len((string)sl.GetKey(iSrnCount)) - 36); //strip off GUID;
            if (sf.Trim(sFamilyName) != "")
            {
               sLink = sLinks[(int)sl.GetByIndex(iSrnCount)].ToString();
               sItemCnt = iSrnCnt[(int)sl.GetByIndex(iSrnCount)].ToString();
               sw1.WriteLine("<A HREF=" + QUOTE + sLink + QUOTE + ">" + sFamilyName + "</A>");
               if (m_cfg.AddSurnameCount == true) sw1.WriteLine("(" + sItemCnt + ")");
               sw1.WriteLine(",&nbsp; ");
            }
         } // iSrnCount

         sw1.WriteLine("</OL>");

         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<EM><CENTER>");
         if (m_cfg.FamFilePrefix == "fam")
         {
            sw1.WriteLine("<A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<A HREF=" + QUOTE + m_cfg.FamFilePrefix + "_ind_idx.html" + QUOTE + ">");
         }
         sw1.WriteLine("Index");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<EM><CENTER>");
         sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
         sw1.WriteLine("Table Of Contents");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<HR NOSHADE SIZE=1>");

         if (m_cfg.AddUserCopyright == true && m_cfg.AuthorsName != "")
         {
            sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
            sw1.Write("Copyright &copy; " + DateTime.Now.ToString("yyyy") + "&nbsp;");
            if (m_cfg.AuthorsEmail != "") sw1.Write("<A href=" + QUOTE + "mailto:" + m_cfg.AuthorsEmail + QUOTE + ">");
            sw1.Write(m_cfg.AuthorsName);
            if (m_cfg.AuthorsEmail != "") sw1.Write("</A>");
            sw1.WriteLine("</CENTER></P></FONT>");
         }

         sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
         sw1.WriteLine("This page was created on " + DateTime.Now.ToString("MM/dd/yy") + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
         sw1.WriteLine("Copyright &copy; 1999-2007 D. M. DeBacker");
         sw1.WriteLine("</CENTER></P></FONT>");
         sw1.WriteLine("</BODY>");
         sw1.WriteLine("</HTML>");

         sw1.Close();
         fs1.Close();

      }


      /// <summary>
      /// Summary of BuildTableOfContents.
      /// </summary>
      /// 		
      private void BuildTableOfContents()
      {
         string sFile;
         //			string  QUOTE;
         string sFirstFile;
         int iCnt;
         string sSurname;
         FileStream fs1;
         StreamWriter sw1;

         char QUOTE = '"';

         sFile = m_cfg.HtmlPath + "\\index.htm";

         fs1 = new FileStream(sFile, FileMode.Create);
         sw1 = new StreamWriter(fs1);

         sw1.WriteLine("<HTML>");

         sw1.WriteLine("<HEAD>");
         if (m_cfg.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
         sw1.WriteLine("<TITLE>" + m_cfg.MainPageTitle + "</TITLE>");
         sw1.WriteLine("<META NAME=" + QUOTE + "Generator" + QUOTE + " CONTENT=" + QUOTE + "UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");


         //optionally add keywords to page
         //if the surname count is greater that five, add it
         if ((m_cfg.AddKeywords == true))
         {
            sw1.Write("<META NAME=" + QUOTE + "keywords" + QUOTE + " CONTENT=" + QUOTE + "genealogy,geneology,GENEALOGY,GENEOLOGY,ancestry,family history,heritage,family tree");
            for (iCnt = 0; iCnt <= MySurnames.Count - 1; iCnt++)
            { //- 1
               sSurname = sf.Trim(MySurnames[iCnt].FamilyName);
               if (sSurname != "" && MySurnames[iCnt].NumItems > 5)
               {
                  sw1.Write("," + sSurname);
               }
            } // iCnt
            sw1.WriteLine(QUOTE + ">");

            sw1.WriteLine("<META HTTP-EQUIV=" + QUOTE + "keywords" + QUOTE + " CONTENT=" + QUOTE + "genealogy geneology GENEALOGY GENEOLOGY ancestry family history heritage family tree" + QUOTE + ">");
         }

         sw1.WriteLine("</HEAD>");
         if (m_cfg.UseBackground)
         {
            sw1.WriteLine("<body background=" + QUOTE + m_cfg.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         sw1.WriteLine("<p><a name=" + QUOTE + "TOP" + QUOTE + ">&nbsp;</a></p>");
         if (m_cfg.UseBanner)
         {
            sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + m_cfg.BannerFile + QUOTE + "></p>");
         }
         sw1.WriteLine("<H1>" + m_cfg.MainPageTitle + "</H1>");
         sw1.WriteLine("</CENTER><CENTER>Last updated " + DateTime.Now.ToString("MMMM dd, yyyy") + "</CENTER><HR>");
         sw1.WriteLine("<H2>Table of Contents</H2>");
         sw1.WriteLine("<UL>");
         sFirstFile = m_cfg.FamFilePrefix + localSettings.FirstFamily.ToString("000") + ".html";
         sw1.WriteLine("<LI><A HREF=" + QUOTE + sFirstFile + QUOTE + ">Family Pages</A>");

         if (m_cfg.FamFilePrefix == "fam")
         {
            sw1.WriteLine(" <LI><A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">Index of Names</A>");
         }
         else
         {
            sw1.WriteLine(" <LI><A HREF=" + QUOTE + m_cfg.FamFilePrefix + "_ind_idx.html" + QUOTE + ">Index of Names</A>");
         }

         if (MySources.Count > 0)
         {
            if (m_cfg.FamFilePrefix == "fam")
            {
               sw1.WriteLine("<LI><A HREF=" + QUOTE + "sources.html" + QUOTE + ">Sources (Bibliography)</A>");
            }
            else
            {
               sw1.WriteLine("<LI><A HREF=" + QUOTE + m_cfg.FamFilePrefix + "_sources.html" + QUOTE + ">Sources (Bibliography)</A>");
            }
         }
         if (m_cfg.FamFilePrefix == "fam")
         {
            sw1.WriteLine("<LI><A href=" + QUOTE + "surnames.html" + QUOTE + ">Surnames</A>");
         }
         else
         {
            sw1.WriteLine("<LI><A href=" + QUOTE + m_cfg.FamFilePrefix + "_surnames.html" + QUOTE + ">Surnames</A>");
         }
         if (m_cfg.CreateStatsPage == true)
         {
            if (m_cfg.FamFilePrefix == "fam")
            {
               sw1.WriteLine("<LI><A href=" + QUOTE + "stats.htm" + QUOTE + ">Statistics</A>");
            }
            else
            {
               sw1.WriteLine("<LI><A href=" + QUOTE + m_cfg.FamFilePrefix + "_stats.htm" + QUOTE + ">Statistics</A>");
            }
         }
         if (m_cfg.CreateChronoPage == true)
         {
            if (m_cfg.FamFilePrefix == "fam")
            {
               sw1.WriteLine("<LI><A href=" + QUOTE + "chrono.htm" + QUOTE + ">Chronology Of Events</A>");
            }
            else
            {
               sw1.WriteLine("<LI><A href=" + QUOTE + m_cfg.FamFilePrefix + "_chrono.htm" + QUOTE + ">Chronology Of Events</A>");
            }
         }
         if (m_cfg.CreateLocPage == true)
         {
            if (m_cfg.FamFilePrefix == "fam")
            {
               sw1.WriteLine("<LI><A href=" + QUOTE + "locations.html" + QUOTE + ">List Of Locations &amp; Place Names</A>");
            }
            else
            {
               sw1.WriteLine("<LI><A href=" + QUOTE + m_cfg.FamFilePrefix + "_locations.html" + QUOTE + ">List Of Locations &amp; Place Names</A>");
            }
         }
         if (m_cfg.CreateOccupationsPage == true)
         {
            if (m_cfg.FamFilePrefix == "fam")
            {
               sw1.WriteLine("<LI><A href=" + QUOTE + "occupations.html" + QUOTE + ">Occupations</A>");
            }
            else
            {
               sw1.WriteLine("<LI><A href=" + QUOTE + m_cfg.FamFilePrefix + "_occupations.html" + QUOTE + ">Occupations</A>");
            }
         }
         sw1.WriteLine("</LI>");
         sw1.WriteLine("</UL>");
         sw1.WriteLine("<HR>");
         if (m_cfg.AuthorsUrl != "")
         {
            sw1.WriteLine("<center><a href=" + QUOTE + m_cfg.AuthorsUrl + QUOTE + "Main Page</a></center>");
         }
         sw1.WriteLine("</BODY>");
         sw1.WriteLine("</HTML>");

         sw1.Close();
         fs1.Close();

      }

      /// <summary>
      /// Summary of BuildStatisticsPage.
      /// </summary>
      /// 		
      private void BuildStatisticsPage()
      {
         string sFile;
         int iCnt;
         FileStream fs1;
         StreamWriter sw1;

         float sngSources;
         float sngNotes;
         int iMissBirthDate = 0;
         int iMissBirthPlace = 0;
         int iPartBirthdate = 0;
         int iMissDeathDate = 0;
         int iPartDeathDate = 0;
         int iMissDeathPlace = 0;
         int NumInds;
         float sngStat;
         MoreStats myMoreStats = new MoreStats();

         char QUOTE = '"';

         if (m_cfg.FamFilePrefix == "fam")
         {
            sFile = m_cfg.HtmlPath + "\\stats.htm";
         }
         else
         {
            sFile = m_cfg.HtmlPath + "\\" + m_cfg.FamFilePrefix + "_stats.htm";
         }

         fs1 = new FileStream(sFile, FileMode.Create);
         sw1 = new StreamWriter(fs1);

         sw1.WriteLine("<html>");
         sw1.WriteLine("<head>");
         if (m_cfg.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
         sw1.WriteLine("<title>Statistics for " + m_cfg.MainPageTitle + "</title>");
         sw1.WriteLine("</head>");
         if (m_cfg.UseBackground)
         {
            sw1.WriteLine("<body background=" + QUOTE + m_cfg.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         if (m_cfg.UseBanner)
         {
            sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + m_cfg.BannerFile + QUOTE + "></p>");
         }
         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<center><h1>Statistics for " + m_cfg.MainPageTitle + "</h1><center>");
         sw1.WriteLine("<div align=" + QUOTE + "left" + QUOTE + ">");
         sw1.WriteLine("<TABLE BORDER=" + QUOTE + "0" + QUOTE + " CELLPADDING=" + QUOTE + "0" + QUOTE + " CELLSPACING=" + QUOTE + "0" + QUOTE + " WIDTH=" + QUOTE + "100%" + QUOTE + ">");
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Source:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.Source + "</td>");
         sw1.WriteLine("</TR>");
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Source Name:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.SourceName + "</td>");
         sw1.WriteLine("</TR>");
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Source Version:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.Version + "</td>");
         sw1.WriteLine("</TR>");
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Creation Date:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.CreationDate + "</td>");
         sw1.WriteLine("</TR>");
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Creation Time:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.CreationTime + "</td>");
         sw1.WriteLine("</TR>");
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">GEDCOM File Name:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.SourceFile + "</td>");
         sw1.WriteLine("</TR>");
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Submitter Name:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.SubmitterName + "</td>");
         sw1.WriteLine("</TR>");
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Submitter E-mail:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.SubmitterEmail + "</td>");
         sw1.WriteLine("</TR>");
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Number Of Individuals:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyIndividuals.Count.ToString() + "</td>");
         sw1.WriteLine("</TR>");
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Number Of Families:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFamilies.Count.ToString() + "</td>");
         sw1.WriteLine("</TR>");
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Number Of Notes:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyNotes.Count.ToString() + "</td>");
         sw1.WriteLine("</TR>");
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Number Of Sources:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MySources.Count.ToString() + "</td>");
         sw1.WriteLine("</TR>");

         if (MyNotes.Count > 0)
         {
            sngNotes = (float)MyNotes.Count / MyIndividuals.Count;
            sw1.WriteLine("<TR>");
            sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Notes / Individuals:</td>");
            sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngNotes.ToString("#,##0.00;;;Nil") + "</td>");
            sw1.WriteLine("</TR>");
         }
         else
         {
            sw1.WriteLine("<TR>");
            sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Notes / Individuals:</td>");
            sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">0</td>");
            sw1.WriteLine("</TR>");
         }

         if (MySources.Count > 0)
         {
            sngSources = (float)MySources.Count / MyIndividuals.Count;
            sw1.WriteLine("<TR>");
            sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Sources / Individuals:</td>");
            sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngSources.ToString("#,##0.00;;;Nil") + "</td>");
            sw1.WriteLine("</TR>");
         }
         else
         {
            sw1.WriteLine("<TR>");
            sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Sources / Individuals:</td>");
            sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">0</td>");
            sw1.WriteLine("</TR>");
         }

         NumInds = MyIndividuals.Count;

         if (NumInds > 0)
         {
            for (iCnt = 0; iCnt <= NumInds - 1; iCnt++)
            {
               if (sf.Trim(MyIndividuals[iCnt].BirthDateText) == "") iMissBirthDate = iMissBirthDate + 1;
               if (sf.IsDate(MyIndividuals[iCnt].BirthDateText) == false && sf.Trim(MyIndividuals[iCnt].BirthDateText) != "") iPartBirthdate = iPartBirthdate + 1;
               if (sf.Trim(MyIndividuals[iCnt].DeathDateText) == "") iMissDeathDate = iMissDeathDate + 1;
               if (sf.IsDate(MyIndividuals[iCnt].DeathDateText) == false && sf.Trim(MyIndividuals[iCnt].DeathDateText) != "") iPartDeathDate = iPartDeathDate + 1;
               if (sf.Trim(MyIndividuals[iCnt].BirthPlace) == "") iMissBirthPlace = iMissBirthPlace + 1;
               if (sf.Trim(MyIndividuals[iCnt].DeathPlace) == "") iMissDeathPlace = iMissDeathPlace + 1;
            } // iCnt
         }

         sngStat = (float)iMissBirthDate / MyIndividuals.Count;
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> % Missing BirthDates:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngStat.ToString("#,##0.00;;;Nil") + "</td>");
         sw1.WriteLine("</TR>");

         sngStat = (float)iPartBirthdate / MyIndividuals.Count;
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> % Partial BirthDates:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngStat.ToString("#,##0.00;;;Nil") + "</td>");
         sw1.WriteLine("</TR>");

         sngStat = (float)iMissBirthPlace / MyIndividuals.Count;
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> % Missing Birth Place:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngStat.ToString("#,##0.00;;;Nil") + "</td>");
         sw1.WriteLine("</TR>");

         sngStat = (float)iMissDeathDate / MyIndividuals.Count;
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> % Missing Death Dates:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngStat.ToString("#,##0.00;;;Nil") + "</td>");
         sw1.WriteLine("</TR>");

         sngStat = (float)iPartDeathDate / MyIndividuals.Count;
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> % Partial Death Dates::</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngStat.ToString("#,##0.00;;;Nil") + "</td>");
         sw1.WriteLine("</TR>");

         sngStat = (float)iMissDeathPlace / MyIndividuals.Count;
         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> % Missing Death Place:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngStat.ToString("#,##0.00;;;Nil") + "</td>");
         sw1.WriteLine("</TR>");

         myMoreStats = GetMoreStats();

         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> Born Before 1600:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + myMoreStats.CountBornBefore1600.ToString() + "</td>");
         sw1.WriteLine("</TR>");

         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> Born in 17th C.:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + myMoreStats.CountBorn17thCentury.ToString() + "</td>");
         sw1.WriteLine("</TR>");

         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> Born in 18th C.:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + myMoreStats.CountBorn18thCentury.ToString() + "</td>");
         sw1.WriteLine("</TR>");

         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> Born in 19th C.:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + myMoreStats.CountBorn19thCentury.ToString() + "</td>");
         sw1.WriteLine("</TR>");

         sw1.WriteLine("<TR>");
         sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> Born in 20th C.:</td>");
         sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + myMoreStats.CountBorn20thCentury.ToString() + "</td>");
         sw1.WriteLine("</TR>");


         sw1.WriteLine("</TABLE>");
         sw1.WriteLine("</div>");

         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<EM><CENTER>");
         if (m_cfg.FamFilePrefix == "fam")
         {
            sw1.WriteLine("<A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<A HREF=" + QUOTE + m_cfg.FamFilePrefix + "_ind_idx.html" + QUOTE + ">");
         }
         sw1.WriteLine("Index");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<EM><CENTER>");
         sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
         sw1.WriteLine("Table Of Contents");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<HR NOSHADE SIZE=1>");

         if (m_cfg.AddUserCopyright == true && m_cfg.AuthorsName != "")
         {
            sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
            sw1.Write("Copyright &copy; " + DateTime.Now.ToString("yyyy") + "&nbsp;");
            if (m_cfg.AuthorsEmail != "") sw1.Write("<A href=" + QUOTE + "mailto:" + m_cfg.AuthorsEmail + QUOTE + ">");
            sw1.Write(m_cfg.AuthorsName);
            if (m_cfg.AuthorsEmail != "") sw1.Write("</A>");
            sw1.WriteLine("</CENTER></P></FONT>");
         }

         sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
         sw1.WriteLine("This page was created on " + DateTime.Now.ToString("MM/dd/yy") + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
         sw1.WriteLine("Copyright &copy; 1999-2007 D. M. DeBacker");
         sw1.WriteLine("</CENTER></P></FONT>");
         sw1.WriteLine("</BODY>");
         sw1.WriteLine("</HTML>");

         sw1.Close();
         fs1.Close();

      }


      /// <summary>
      /// Summary of BuildTimeLinePage.
      /// </summary>
      /// 		
      private void BuildTimeLinePage()
      {
         string FilePath;
         int iYear;
         string sActualDate;
         string sIndexDate;
         DateTime dtDummyDate;
         FileStream fs1;
         StreamWriter sw1;

         int iCnt;
         int iNumItems;

         GetTimeLineEvents();

         if (m_cfg.FamFilePrefix == "fam")
         {
            FilePath = m_cfg.HtmlPath + "\\chrono.htm";
         }
         else
         {
            FilePath = m_cfg.HtmlPath + "\\" + m_cfg.FamFilePrefix + "_chrono.htm";
         }

         char Q = '"';
         iYear = 0;


         iNumItems = MyTimeLineEntries.Count;
         SortedList sl = new SortedList(iNumItems);

         for (iCnt = 0; iCnt <= iNumItems - 1; iCnt++)
         {
            if (MyTimeLineEntries[iCnt].ActualDate == System.DateTime.FromOADate(0))
            {
               dtDummyDate = sf.DateValue("12/31/" + MyTimeLineEntries[iCnt].TheYear.ToString());
               sIndexDate = dtDummyDate.ToString("yyyyMMdd");
            }
            else
            {
               sIndexDate = MyTimeLineEntries[iCnt].ActualDate.ToString("yyyyMMdd");
            }
            sl.Add(sIndexDate + CreateGUIDKey(), iCnt);
         } //

         fs1 = new FileStream(FilePath, FileMode.Create);
         sw1 = new StreamWriter(fs1);

         sw1.WriteLine("<HTML>");
         sw1.WriteLine("<HEAD>");
         if (m_cfg.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
         sw1.WriteLine("<META NAME=" + Q + "GENERATOR" + Q + " Content=" + Q + "Microsoft Visual Studio 6.0" + Q + ">");
         sw1.WriteLine("<TITLE>Chronology Of Events</TITLE>");
         sw1.WriteLine("</HEAD>");
         if (m_cfg.UseBackground)
         {
            sw1.WriteLine("<body background=" + Q + m_cfg.BackgroundFile + Q + " link=" + Q + "#0000FF" + Q + " vlink=" + Q + "#800080" + Q + " bgproperties=" + Q + "fixed" + Q + " leftmargin=" + Q + "100" + Q + ">");
         }
         else
         {
            sw1.WriteLine("<body link=" + Q + "#0000FF" + Q + " vlink=" + Q + "#800080" + Q + " bgproperties=" + Q + "fixed" + Q + " leftmargin=" + Q + "100" + Q + ">");
         }
         if (m_cfg.UseBanner)
         {
            sw1.WriteLine("<p align=" + Q + "center" + Q + "><img src=" + Q + m_cfg.BannerFile + Q + " width=" + Q + "224" + Q + " height=" + Q + "38" + Q + "></p>");
         }
         sw1.WriteLine("<h1 align=" + Q + "center" + Q + "><font color=" + Q + "black" + Q + " face=" + Q + "Book Antiqua" + Q + ">Chronology Of Events</font></h1>");
         sw1.WriteLine("<hr>");

         for (iCnt = 0; iCnt <= iNumItems - 1; iCnt++)
         {

            if (iYear != MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].TheYear)
            {
               if (iYear != 0)
               { //end the previous list
                  sw1.WriteLine("</ul>");
               }

               iYear = MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].TheYear;
               if (iYear < 1000)
               {
                  sw1.WriteLine("<H2><FONT color=" + Q + "black" + Q + " face=" + Q + "Book Antiqua" + Q + ">AD " + iYear.ToString() + "</FONT></H2>");
               }
               else
               {
                  sw1.WriteLine("<H2><FONT color=" + Q + "black" + Q + " face=" + Q + "Book Antiqua" + Q + ">" + iYear.ToString() + "</FONT></H2>");
               }
               sw1.WriteLine("<ul>");//start a new list;
            }

            sw1.WriteLine("<li style=" + Q + "color: " + MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].ColorCode + Q + ">");

            if (MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].ActualDate != System.DateTime.FromOADate(0))
            {
               sActualDate = MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].ActualDate.ToString("dd MMM");
               sw1.WriteLine("<b><FONT color=" + Q + "black" + Q + ">" + sActualDate + "</FONT></b>&nbsp;-&nbsp;");
            }

            if (MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].IsAbout == true)
            {
               switch (MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].EstimateStyle)
               {
                  case 1: goto case 2;
                  case 2: goto case 3;
                  case 3: goto case 6;
                  case 6:
                     sw1.WriteLine("<FONT color=" + Q + "black" + Q + ">It was about this time that " + MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].EventDetails + "</FONT>");
                     break;
                  case 4:
                     sw1.WriteLine("<FONT color=" + Q + "black" + Q + ">It was before this date that " + MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].EventDetails + "</FONT>");
                     break;
                  case 5:
                     sw1.WriteLine("<FONT color=" + Q + "black" + Q + ">It was after this date that " + MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].EventDetails + "</FONT>");
                     break;
               }
            }
            else
            {
               sw1.WriteLine("<FONT color=" + Q + "black" + Q + ">" + MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].EventDetails + "</FONT>");
            }
            sw1.WriteLine("</li>");
         } // iCnt

         sw1.WriteLine("</ul>");

         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<EM><CENTER>");
         if (m_cfg.FamFilePrefix == "fam")
         {
            sw1.WriteLine("<A HREF=" + Q + "ind_idx.html" + Q + ">");
         }
         else
         {
            sw1.WriteLine("<A HREF=" + Q + m_cfg.FamFilePrefix + "_ind_idx.html" + Q + ">");
         }
         sw1.WriteLine("Index");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<EM><CENTER>");
         sw1.WriteLine("<A HREF=" + Q + "index.htm" + Q + ">");
         sw1.WriteLine("Table Of Contents");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<HR NOSHADE SIZE=1>");

         if (m_cfg.AddUserCopyright == true && m_cfg.AuthorsName != "")
         {
            sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
            sw1.Write("Copyright &copy; " + DateTime.Now.ToString("yyyy") + "&nbsp;");
            if (m_cfg.AuthorsEmail != "") sw1.Write("<A href=" + Q + "mailto:" + m_cfg.AuthorsEmail + Q + ">");
            sw1.Write(m_cfg.AuthorsName);
            if (m_cfg.AuthorsEmail != "") sw1.Write("</A>");
            sw1.WriteLine("</CENTER></P></FONT>");
         }

         sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
         sw1.WriteLine("This page was created on " + DateTime.Now.ToString("MM/dd/yy") + " using <a href=" + Q + "http://gatheringleaves.org/uged" + Q + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
         sw1.WriteLine("Copyright &copy; 1999-2007 D. M. DeBacker");
         sw1.WriteLine("</CENTER></P></FONT>");
         sw1.WriteLine("</BODY>");
         sw1.WriteLine("</HTML>");

         sw1.Close();
         fs1.Close();

      }


      #endregion

      #region Methods for building misc. files
      /// <summary>
      /// Summary of BuildGendexFile.
      /// </summary>
      /// 		
      private void BuildGendexFile()
      {
         string sFile;
         int iCnt;
         int iGendexEntrys;
         FileStream fs1;
         StreamWriter sw1;


         sFile = m_cfg.HtmlPath + "\\GENDEX.txt";
         fs1 = new FileStream(sFile, FileMode.Create);
         sw1 = new StreamWriter(fs1);

         iGendexEntrys = MyGendices.Count;

         if (iGendexEntrys > 0)
         {
            for (iCnt = 0; iCnt <= iGendexEntrys - 1; iCnt++)
            {

               if (sf.Trim(MyGendices[iCnt].Surname) != "")
               {
                  sw1.Write(MyGendices[iCnt].PageUrl + "|");
                  sw1.Write(MyGendices[iCnt].Surname + "|");
                  sw1.Write(MyGendices[iCnt].Fullname + "|");
                  if (sf.IsDate(MyGendices[iCnt].Birthdate))
                  {
                     sw1.Write(sf.DateValue(MyGendices[iCnt].Birthdate).ToString("dd MMM yyyy") + "|");
                  }
                  else
                  {
                     sw1.Write(MyGendices[iCnt].Birthdate + "|");
                  }
                  sw1.Write(MyGendices[iCnt].BirthPlace + "|");
                  if (sf.IsDate(MyGendices[iCnt].DeathDate))
                  {
                     sw1.Write(sf.DateValue(MyGendices[iCnt].DeathDate).ToString("dd MMM yyyy") + "|");
                  }
                  else
                  {
                     sw1.Write(MyGendices[iCnt].DeathDate + "|");
                  }
                  sw1.WriteLine(MyGendices[iCnt].DeathPlace + "|");
               }
            }
         } // iCnt

         sw1.Close();
         fs1.Close();

      }


      /// <summary>
      /// Summary of BuildLocationsReport.
      /// </summary>
      /// 		
      private void BuildLocationsReport()
      {
         string sFile;
         //			string  sData;
         int iLocCount;
         int iNumLocs;
         //			string  QUOTE;
         string sCurrLoc;
         string sPrevLoc;
         string sLocation;
         string sFile2;

         FileStream fs1;
         StreamWriter sw1;

         FileStream fs2;
         StreamWriter sw2;

         GetLocations();

         iNumLocs = MyLocations.Count;

         SortedList sl = new SortedList(iNumLocs);

         char QUOTE = '"';

         if (iNumLocs == 0) return;


         for (iLocCount = 0; iLocCount <= iNumLocs - 1; iLocCount++)
         {
            sl.Add(MyLocations[iLocCount].LocationName + CreateGUIDKey(), iLocCount);
         } // iLocCount

         if (m_cfg.FamFilePrefix == "fam")
         {
            sFile = m_cfg.HtmlPath + "\\locations.html";
         }
         else
         {
            sFile = m_cfg.HtmlPath + "\\" + m_cfg.FamFilePrefix + "_locations.html";
         }

         fs1 = new FileStream(sFile, FileMode.Create);
         sw1 = new StreamWriter(fs1);

         sFile2 = m_cfg.HtmlPath + "\\loc_report.txt";

         fs2 = new FileStream(sFile2, FileMode.Create);
         sw2 = new StreamWriter(fs2);

         //file header
         sw1.WriteLine("<HTML>");
         sw1.WriteLine("<HEAD>");
         if (m_cfg.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
         sw1.WriteLine("<TITLE>Locations Report</TITLE>");
         sw1.WriteLine("<META NAME=" + QUOTE + " Generator" + QUOTE + " CONTENT=" + QUOTE + " UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");
         sw1.WriteLine("</HEAD>");
         if (m_cfg.UseBackground)
         {
            sw1.WriteLine("<body background=" + QUOTE + m_cfg.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + ">");
         }
         sw1.WriteLine("<p><a name=" + QUOTE + "TOP" + QUOTE + ">&nbsp;</a></p>");
         if (m_cfg.UseBanner)
         {
            sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + m_cfg.BannerFile + QUOTE + "></p>");
         }
         sw1.WriteLine("<h1><p align=" + QUOTE + "center" + QUOTE + ">Locations</p></h1>");
         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sPrevLoc = "#";
         for (iLocCount = 0; iLocCount <= iNumLocs - 1; iLocCount++)
         {
            if (_didCancel) goto BUILDLOC_EXIT;
            sLocation = sf.Left((string)sl.GetKey(iLocCount), sf.Len((string)sl.GetKey(iLocCount)) - 36); //strip off GUID;
            if (sLocation != "")
            {
               sCurrLoc = sLocation;
               if (sPrevLoc != sCurrLoc)
               {
                  sw1.WriteLine("</ul>"); //end prev list;
                  sw1.Write("<H2>");
                  sw1.Write("<A NAME=LOC" + iLocCount.ToString("000") + ">" + sCurrLoc + "</A>");
                  sw2.WriteLine(sCurrLoc);
                  sw1.WriteLine("</H2>");
                  sPrevLoc = sCurrLoc;
                  sw1.WriteLine("<ul>");//start a new list;
               }
               sw1.WriteLine("<li>" + MyLocations[(int)sl.GetByIndex(iLocCount)].PersonName + " (" + EventDescription((MyLocations[(int)sl.GetByIndex(iLocCount)].EventType)) + ")</li>");
            }
         } // iLocCount

         sw1.WriteLine("</ul>");//end prev list;

         sw1.WriteLine("<HR NOSHADE SIZE=1>");
         sw1.WriteLine("<EM><CENTER>");
         if (m_cfg.FamFilePrefix == "fam")
         {
            sw1.WriteLine("<A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">");
         }
         else
         {
            sw1.WriteLine("<A HREF=" + QUOTE + m_cfg.FamFilePrefix + "_ind_idx.html" + QUOTE + ">");
         }
         sw1.WriteLine("Index");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<EM><CENTER>");
         sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
         sw1.WriteLine("Table Of Contents");
         sw1.WriteLine("</A>");
         sw1.WriteLine("</CENTER></EM>");
         sw1.WriteLine("<HR NOSHADE SIZE=1>");

         if (m_cfg.AddUserCopyright == true && m_cfg.AuthorsName != "")
         {
            sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
            sw1.Write("Copyright &copy; " + DateTime.Now.ToString("yyyy") + "&nbsp;");
            if (m_cfg.AuthorsEmail != "") sw1.Write("<A href=" + QUOTE + "mailto:" + m_cfg.AuthorsEmail + QUOTE + ">");
            sw1.Write(m_cfg.AuthorsName);
            if (m_cfg.AuthorsEmail != "") sw1.Write("</A>");
            sw1.WriteLine("</CENTER></P></FONT>");
         }

         sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
         sw1.WriteLine("This page was created on " + DateTime.Now.ToString("MM/dd/yy") + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
         sw1.WriteLine("Copyright &copy; 1999-2007 D. M. DeBacker");
         sw1.WriteLine("</CENTER></P></FONT>");
         sw1.WriteLine("</BODY>");
         sw1.WriteLine("</HTML>");
      BUILDLOC_EXIT:
         sw1.Close();
         fs1.Close();

         sw2.Close();
         fs2.Close();

      }


      /// <summary>
      /// Called by BuildLocationsReport to create as master list of all locations
      /// </summary>
      /// 		
      private void GetLocations()
      {
         //added in 3.01
         int iCnt;
         int jCnt;
         int iTotItems;
         string sEventDetails;
         string sLocation;
         string sHusband;
         string sWife;
         string sName;
         int iNumEvents;
         string sTemp;
         int iPageNum;
         string sLinkPage;
         char Q = '"';

         //wipe everything out
         MyLocations = new Locations();

         //marriages
         iTotItems = MyFamilies.Count;
         if (iTotItems != 0)
         {
            for (iCnt = 0; iCnt <= iTotItems - 1; iCnt++)
            {
               sEventDetails = "";
               //MainForm.pbFile.value = (iCnt / iTotItems) * 100
               sLocation = sf.Trim(MyFamilies[iCnt].MarriagePlace);

               if (sf.Trim(sLocation) == "") continue;

               if (sf.Left(sLocation, 1) == "[" || sf.Left(sLocation, 1) == "<")
               {
                  switch (m_cfg.LocEstimateMethod)
                  {
                     case 0: //do not list;
                        continue;
                     case 1://treat same;
                        sLocation = sf.Mid(sLocation, 2, sf.Len(sLocation) - 2);
                        break;
                     case 2://list at end;
                        //nothing to do then
                        break;
                  }
               }

               if (m_cfg.LocReverseOrder)
               {
                  sLocation = ReverseLocation(sLocation);
               }

               if (MyFamilies[iCnt].Husband != "?")
               {
                  sHusband = MyIndividuals[MyFamilies[iCnt].Husband].Forenames + " " + MyIndividuals[MyFamilies[iCnt].Husband].Surname;
                  if (MyIndividuals[MyFamilies[iCnt].Husband].Suffix != "")
                  {
                     sHusband = sHusband + ", " + MyIndividuals[MyFamilies[iCnt].Husband].Suffix;
                  }
               }
               else
               {
                  sHusband = "?";
               }

               if (MyFamilies[iCnt].Wife != "?")
               {
                  sWife = MyIndividuals[MyFamilies[iCnt].Wife].Forenames + " " + MyIndividuals[MyFamilies[iCnt].Wife].Surname;
                  if (MyIndividuals[MyFamilies[iCnt].Wife].Suffix != "")
                  {
                     sWife = sWife + ", " + MyIndividuals[MyFamilies[iCnt].Wife].Suffix;
                  }
               }
               else
               {
                  sWife = "?";
               }

               //@F5@ - example family id - then numeric portion equals the page number
               sTemp = sf.Right(MyFamilies[iCnt].ID, sf.Len(MyFamilies[iCnt].ID) - 2);
               iPageNum = System.Convert.ToInt32(sf.Left(sTemp, sf.Len(sTemp) - 1));
               sLinkPage = m_cfg.FamFilePrefix + iPageNum.ToString("000") + ".html";

               if (sHusband != "?")
               {
                  if (m_cfg.ChronoLinks == true) sEventDetails = "<a href=" + Q + sLinkPage + Q + ">";
                  sEventDetails = sEventDetails + sHusband;
                  if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "</a>";
               }
               else
               {
                  sEventDetails = sHusband;
               }
               sEventDetails = sEventDetails + " and ";
               if (sWife != "?")
               {
                  if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "<a href=" + Q + sLinkPage + Q + ">";
                  sEventDetails = sEventDetails + sWife;
                  if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "</a>";
               }
               else
               {
                  sEventDetails = sEventDetails + sWife;
               }
               if (m_cfg.LocDisplayEventDates == true && MyFamilies[iCnt].MarriageDateText != "")
               {
                  sEventDetails = sEventDetails + " - " + MyFamilies[iCnt].MarriageDateText;
               }
               if (MyFamilies[iCnt].MarriagePlace != "")
               {
                  MyLocations.Add(sLocation, sEventDetails, LifeEvent.EventTypes.etMarriage, CreateGUIDKey());
               }
            } // iCnt
         }

         //births
         iTotItems = MyIndividuals.Count;
         if (iTotItems != 0)
         {
            for (iCnt = 0; iCnt <= iTotItems - 1; iCnt++)
            {
               sEventDetails = "";
               //MainForm.pbFile.value = (iCnt / iTotItems) * 100
               sLocation = sf.Trim(MyIndividuals[iCnt].BirthPlace);
               if (sf.Trim(sLocation) == "") continue;

               if (sf.Left(sLocation, 1) == "[" || sf.Left(sLocation, 1) == "<")
               {
                  switch (m_cfg.LocEstimateMethod)
                  {
                     case 0: //do not list;
                        continue;
                     case 1: //treat same;
                        sLocation = sf.Mid(sLocation, 2, sf.Len(sLocation) - 2);
                        break;
                     case 2: //list at end;
                        //nothing to do then
                        break;
                  }
               }

               if (m_cfg.LocReverseOrder)
               {
                  sLocation = ReverseLocation(sLocation);
               }

               sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
               if (MyIndividuals[iCnt].Suffix != "")
               {
                  sName = sName + ", " + MyIndividuals[iCnt].Suffix;
               }
               if (m_cfg.ChronoLinks == true) sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
               sEventDetails = sEventDetails + sName;
               if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "</a>";
               if (m_cfg.LocDisplayEventDates == true && MyIndividuals[iCnt].BirthDateText != "")
               {
                  sEventDetails = sEventDetails + " - " + MyIndividuals[iCnt].BirthDateText;
               }
               if (MyIndividuals[iCnt].BirthPlace != "")
               {
                  MyLocations.Add(sLocation, sEventDetails, LifeEvent.EventTypes.etBirth, CreateGUIDKey());
               }
            } // iCnt
         }

         //deaths
         iTotItems = MyIndividuals.Count;
         if (iTotItems != 0)
         {
            for (iCnt = 0; iCnt <= iTotItems - 1; iCnt++)
            {
               sEventDetails = "";
               sLocation = sf.Trim(MyIndividuals[iCnt].DeathPlace);
               if (sf.Trim(sLocation) == "") continue;

               if (sf.Left(sLocation, 1) == "[" || sf.Left(sLocation, 1) == "<")
               {
                  switch (m_cfg.LocEstimateMethod)
                  {
                     case 0: //do not list;
                        continue;
                     case 1: //treat same;
                        sLocation = sf.Mid(sLocation, 2, sf.Len(sLocation) - 2);
                        break;
                     case 2: //list at end;
                        //nothing to do then
                        break;
                  }
               }

               if (m_cfg.LocReverseOrder)
               {
                  sLocation = ReverseLocation(sLocation);
               }

               sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
               if (MyIndividuals[iCnt].Suffix != "")
               {
                  sName = sName + ", " + MyIndividuals[iCnt].Suffix;
               }

               if (m_cfg.ChronoLinks == true) sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
               sEventDetails = sEventDetails + sName;
               if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "</a>";
               if (m_cfg.LocDisplayEventDates == true && MyIndividuals[iCnt].DeathDateText != "")
               {
                  sEventDetails = sEventDetails + " - " + MyIndividuals[iCnt].DeathDateText;
               }
               if (MyIndividuals[iCnt].DeathPlace != "")
               {
                  MyLocations.Add(sLocation, sEventDetails, LifeEvent.EventTypes.etDeath, CreateGUIDKey());
               }
            } // iCnt
         }

         //life events
         iTotItems = MyIndividuals.Count;
         if (iTotItems != 0)
         {
            for (iCnt = 0; iCnt <= iTotItems - 1; iCnt++)
            {
               iNumEvents = MyIndividuals[iCnt].LifeEvents.Count;
               if (iNumEvents != 0)
               {
                  for (jCnt = 0; jCnt <= iNumEvents - 1; jCnt++)
                  {
                     if (MyIndividuals[iCnt].LifeEvents[jCnt].EventType == LifeEvent.EventTypes.etBirth 
                        || MyIndividuals[iCnt].LifeEvents[jCnt].EventType == LifeEvent.EventTypes.etDeath) continue;

                     sEventDetails = "";

                     if (MyIndividuals[iCnt].LifeEvents[jCnt].EventType == LifeEvent.EventTypes.etOccupation)
                     {
                        if (m_cfg.IgnoreOccupations == true) continue;
                     }

                     sLocation = sf.Trim(MyIndividuals[iCnt].LifeEvents[jCnt].EventPlace);
                     if (sf.Trim(sLocation) == "") continue;

                     if (sf.Left(sLocation, 1) == "[" || sf.Left(sLocation, 1) == "<")
                     {
                        switch (m_cfg.LocEstimateMethod)
                        {
                           case 0: //do not list;
                              continue;
                           case 1: //treat same;
                              sLocation = sf.Mid(sLocation, 2, sf.Len(sLocation) - 2);
                              break;
                           case 2: //list at end;
                              //nothing to do then
                              break;
                        }
                     }

                     if (m_cfg.LocReverseOrder)
                     {
                        sLocation = ReverseLocation(sLocation);
                     }

                     sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
                     if (MyIndividuals[iCnt].Suffix != "")
                     {
                        sName = sName + ", " + MyIndividuals[iCnt].Suffix;
                     }

                     if (m_cfg.ChronoLinks == true) sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
                     sEventDetails = sEventDetails + sName;
                     if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "</a>";
                     if (m_cfg.LocDisplayEventDates == true && MyIndividuals[iCnt].LifeEvents[jCnt].EventDateString != "")
                     {
                        sEventDetails = sEventDetails + " - " + MyIndividuals[iCnt].LifeEvents[jCnt].EventDateString;
                     }

                     if (MyIndividuals[iCnt].LifeEvents[jCnt].EventPlace != "")
                     {
                        MyLocations.Add(sLocation, sEventDetails, MyIndividuals[iCnt].LifeEvents[jCnt].EventType, CreateGUIDKey());
                     }
                  } // jCnt
               }
            } // iCnt
         }

      }


      #endregion

      #region helper functions
      //HELPER FUNCTIONS

      /// <summary>
      /// Returns a text description of a given event type.
      /// </summary>
      /// <param name=EventType></param>
      /// 		
      private string EventDescription(LifeEvent.EventTypes EventType)
      {
         string eventText = "";

         switch (EventType)
         {
            case LifeEvent.EventTypes.etUnknown: eventText = "Unknown event"; break;
            case LifeEvent.EventTypes.etDeathOfSpouse: eventText = "Death Of Spouse"; break;
            case LifeEvent.EventTypes.etBirth: eventText = "Birth"; break;
            case LifeEvent.EventTypes.etDeath: eventText = "Death"; break;
            case LifeEvent.EventTypes.etBurial: eventText = "Burial"; break;
            case LifeEvent.EventTypes.etOccupation: eventText = "Occupation"; break;
            case LifeEvent.EventTypes.etMarriage: eventText = "Marriage"; break;
            case LifeEvent.EventTypes.etResidence: eventText = "Residence"; break;
            case LifeEvent.EventTypes.etDivorce: eventText = "Divorce"; break;
            case LifeEvent.EventTypes.etImmigration: eventText = "Immigration"; break;
            case LifeEvent.EventTypes.etMilitary: eventText = "Military"; break;
            case LifeEvent.EventTypes.etOther: eventText = "Other"; break;
            case LifeEvent.EventTypes.etElected: eventText = "Elected"; break;
            case LifeEvent.EventTypes.etExcommunicated: eventText = "Excommunicated"; break;
            case LifeEvent.EventTypes.etMission: eventText = "Mission"; break;
            case LifeEvent.EventTypes.etBaptismLDS: eventText = "Baptism LDS"; break;
            case LifeEvent.EventTypes.etBaptism: eventText = "Baptism"; break;
            case LifeEvent.EventTypes.etBar_Mitzvah: eventText = "Bar Mitzvah"; break;
            case LifeEvent.EventTypes.etBat_Mitzvah: eventText = "Bat Mitzah"; break;
            case LifeEvent.EventTypes.etBlessing: eventText = "Blessing"; break;
            case LifeEvent.EventTypes.etCaste: eventText = "Caste"; break;
            case LifeEvent.EventTypes.etCensus: eventText = "Census"; break;
            case LifeEvent.EventTypes.etChristening: eventText = "Christening"; break;
            case LifeEvent.EventTypes.etConfirmation: eventText = "Confirmation"; break;
            case LifeEvent.EventTypes.etConfirmationLDS: eventText = "Confirmation LDS"; break;
            case LifeEvent.EventTypes.etCremation: eventText = "Cremation"; break;
            case LifeEvent.EventTypes.etEducation: eventText = "Education"; break;
            case LifeEvent.EventTypes.etEmigration: eventText = "Emigration"; break;
            case LifeEvent.EventTypes.etEndowmentLDS: eventText = "Endowment LDS"; break;
            case LifeEvent.EventTypes.etFirstCommunion: eventText = "First Communion"; break;
            case LifeEvent.EventTypes.etGraduation: eventText = "Graduation"; break;
            case LifeEvent.EventTypes.etNaturalization: eventText = "Naturalization"; break;
            case LifeEvent.EventTypes.etOrdination: eventText = "Ordination"; break;
            case LifeEvent.EventTypes.etProbate: eventText = "Probate"; break;
            case LifeEvent.EventTypes.etProperty: eventText = "Property"; break;
            case LifeEvent.EventTypes.etReligion: eventText = "Religion"; break;
            case LifeEvent.EventTypes.etRetirement: eventText = "Retirement"; break;
            case LifeEvent.EventTypes.etSealedToParentsLDS: eventText = "Sealed To Parents LDS"; break;
            case LifeEvent.EventTypes.etSSN: eventText = "SSN"; break;
            case LifeEvent.EventTypes.etWill: eventText = "Will"; break;
         }

         return eventText;

      }


      /// <summary>
      /// Summary of FixDate.
      /// </summary>
      /// <param name=sData></param>
      /// 		
      private string FixDate(string sData)
      {
         //fixes dates with EST, ABT, etc.
         string sTemp;
         int x;
         //			int iToPoint;
         string sTemp2 = "";
         bool bHasAnd = false;
         string sDate;

         sDate = StripChar(sData, ".", true);

         sTemp = sf.Trim(sDate);

         if (sf.UCase(sf.Left(sTemp, 3)) == "ABT")
         {
            sTemp = sf.Trim(sf.Right(sTemp, sf.Len(sTemp) - 3));
            if (sf.IsDate(sTemp)) sTemp = sf.DateValue(sTemp).ToString("MMMM dd, yyyy"); ;
            sTemp = "abt. " + sTemp;
         }

         if (sf.UCase(sf.Left(sTemp, 3)) == "CAL")
         {
            sTemp = sf.Trim(sf.Right(sTemp, sf.Len(sTemp) - 3));
            if (sf.IsDate(sTemp)) sTemp = sf.DateValue(sTemp).ToString("MMMM dd, yyyy");
            sTemp = sTemp + " (calc)";
         }

         if (sf.UCase(sf.Left(sTemp, 3)) == "EST")
         {
            sTemp = sf.Trim(sf.Right(sTemp, sf.Len(sTemp) - 3));
            if (sf.IsDate(sTemp)) sTemp = sf.DateValue(sTemp).ToString("MMMM dd, yyyy");
            sTemp = sTemp + " (est)";
         }

         if (sf.UCase(sf.Left(sTemp, 3)) == "BEF")
         {
            sTemp = sf.Trim(sf.Right(sTemp, sf.Len(sTemp) - 3));
            if (sf.IsDate(sTemp)) sTemp = sf.DateValue(sTemp).ToString("MMMM dd, yyyy");
            sTemp = "bef. " + sTemp;
         }

         if (sf.UCase(sf.Left(sTemp, 3)) == "AFT")
         {
            sTemp = sf.Trim(sf.Right(sTemp, sf.Len(sTemp) - 3));
            if (sf.IsDate(sTemp)) sTemp = sf.DateValue(sTemp).ToString("MMMM dd, yyyy");
            sTemp = "aft. " + sTemp;
         }

         if (sf.UCase(sf.Left(sTemp, 3)) == "BET")
         {
            x = sf.InStr(sDate, "-");
            if (x == 0)
            {
               x = sf.InStr(sDate, "AND");
               if (x != 0)
               {
                  bHasAnd = true;
               }
               else
               {
                  bHasAnd = false;
               }
            }
            if (x > 0)
            {
               sTemp = sf.Trim(sf.Mid(sTemp, 5, x - 5));
            }
            else
            {
               sTemp = sf.Trim(sf.Right(sTemp, sf.Len(sTemp) - 3));
            }
            if (sf.IsDate(sTemp)) sTemp = sf.DateValue(sTemp).ToString("MMMM dd, yyyy");

            if (x > 0 && bHasAnd == false)
            {
               sTemp2 = sf.Trim(sf.Right(sDate, sf.Len(sDate) - x));
            }
            else if (x > 0 && bHasAnd == true)
            {
               sTemp2 = sf.Trim(sf.Right(sDate, sf.Len(sDate) - (x + 2)));
            }
            if (sf.IsDate(sTemp2)) sTemp2 = sf.DateValue(sTemp2).ToString("MMMM dd, yyyy");

            sTemp = "between " + sTemp;

            if (x > 0)
            {
               sTemp = sTemp + " and " + sTemp2;
            }

         }

         return sTemp;
      }


      /// <summary>
      /// Summary of FixRin.
      /// </summary>
      /// <param name=sRin></param>
      /// 		
      public string FixRin(string sRin)
      {
         string sTemp;
         sTemp = sf.Trim(sRin);
         sTemp = sf.Right(sTemp, sf.Len(sTemp) - 2);
         sTemp = sf.Left(sTemp, sf.Len(sTemp) - 1);
         return sTemp;
      }

      /// <summary>
      /// if the husband or wife is an empty string change it to a question mark
      /// </summary>
      /// 		
      private void FixFamiliesEach()
      {
         int iNumFams;

         iNumFams = MyFamilies.Count;

         if (iNumFams == 0) return;
         foreach (Family family in MyFamilies)
         {
            if (_didCancel) return;
            if (sf.Trim(family.Husband) == "")
            {
               family.Husband = "?";
            }
            if (sf.Trim(family.Wife) == "")
            {
               family.Wife = "?";
            }
         } // family //iFamCount

      }


      /// <summary>
      /// Summary of MarkAsPrivate.
      /// </summary>
      /// 		
      private void MarkAsPrivate()
      {
         DateTime ActualDate;
         DateTime CutOffDate;

         CutOffDate = new DateTime(DateTime.Now.Year - 80, DateTime.Now.Month, DateTime.Now.Day);

         foreach (Individual person in MyIndividuals)
         {
            if (sf.IsDate(person.BirthDateText) && (sf.Trim(person.DeathDateText) == ""))
            {
               ActualDate = sf.DateValue(person.BirthDateText);
               if (ActualDate > CutOffDate)
               {
                  person.BirthDateText = Privacy;
               }
            }
         } // person

      }


      /// <summary>
      /// Summary of SecondsToHMS.
      /// </summary>
      /// <param name=lSeconds></param>
      /// 		
      private string SecondsToHMS(int lSeconds)
      {
         string sHour;
         string sMinute;
         string sSecond;
         int iHour;
         int iMinute;
         int iSecond;
         int lRemain;

         if (lSeconds >= 3600)
         {
            iHour = (int)(lSeconds / 60 / 60);
            lRemain = lSeconds - ((int)(iHour) * 60 * 60);
         }
         else
         {
            iHour = 0;
            lRemain = lSeconds;
         }

         sHour = iHour.ToString("00");

         if (lSeconds >= 60)
         {
            iMinute = (int)(lRemain / 60);
            lRemain = lSeconds - (((int)(iHour) * 60 * 60) + ((int)(iMinute) * 60));
         }
         else
         {
            iMinute = 0;
            lRemain = lSeconds;
         }

         sMinute = iMinute.ToString("00");

         iSecond = lRemain;
         sSecond = iSecond.ToString("00");

         return (sHour + ":" + sMinute + ":" + sSecond);
      }


      /// <summary>
      /// Summary of GetSoundexCode.
      /// </summary>
      /// <param name=sSurname></param>
      /// 		
      private string GetSoundexCode(string sSurname)
      {

         //1 - B,P,F,V
         //2 - C,S,G,J,K,Q,X,Z
         //3 - D,T
         //4 - L
         //5 - M,N
         //6 - R
         //
         //The letters A,E,I,O,U,Y,H, and W are not coded.
         //Names with adjacent letters having the same equivalent number are coded as one letter with a single number.
         //Surname prefixes are generally not used in the soundex.

         string sSoundex;
         string sTemp;
         int iCnt;
         int iIndx;
         string sChar;
         string sPrevChar;

         if (sSurname == "")
         {
            return "";
         }

         sSurname = sf.Trim(sf.UCase(sSurname));

         if (sf.Left(sSurname, 2) == "KN")
         { //special case for names that begin w/ KN
            sSoundex = "N";
            sTemp = sf.Right(sSurname, sf.Len(sSurname) - 2);
         }
         else
         {
            sSoundex = sf.Left(sSurname, 1);
            sTemp = sf.Right(sSurname, sf.Len(sSurname) - 1);
         }

         iIndx = 0;

         for (iCnt = 1; iCnt <= sf.Len(sTemp); iCnt++)
         {

            sChar = sf.Mid(sTemp, iCnt, 1);

            //if ( sChar != sPrevChar ) {
            switch (sChar)
            {
               case "B":
               case "P":
               case "F":
               case "V":
                  if (sf.Right(sSoundex, 1) != "1")
                  {
                     sSoundex = sSoundex + "1";
                     iIndx = iIndx + 1;
                  }
                  break;
               case "C":
               case "S":
               case "G":
               case "J":
               case "K":
               case "Q":
               case "X":
               case "Z":
                  if (sf.Right(sSoundex, 1) != "2")
                  {
                     sSoundex = sSoundex + "2";
                     iIndx = iIndx + 1;
                  }
                  break;
               case "D":
               case "T":
                  if (sf.Right(sSoundex, 1) != "3")
                  {
                     sSoundex = sSoundex + "3";
                     iIndx = iIndx + 1;
                  }
                  break;
               case "L":
                  if (sf.Right(sSoundex, 1) != "4")
                  {
                     sSoundex = sSoundex + "4";
                     iIndx = iIndx + 1;
                  }
                  break;
               case "M":
               case "N":
                  if (sf.Right(sSoundex, 1) != "5")
                  {
                     sSoundex = sSoundex + "5";
                     iIndx = iIndx + 1;
                  }
                  break;
               case "R":
                  if (sf.Right(sSoundex, 1) != "6")
                  {
                     sSoundex = sSoundex + "6";
                     iIndx = iIndx + 1;
                  }
                  break;
            }
            //}

            sPrevChar = sChar;
            if (iIndx == 3) break; //fixed in 2.1 was set to 4
         } // iCnt

         //pad with zeros
         if (sf.Len(sSoundex) == 1) sSoundex = sSoundex + "000";
         if (sf.Len(sSoundex) == 2) sSoundex = sSoundex + "00";
         if (sf.Len(sSoundex) == 3) sSoundex = sSoundex + "0";

         return sSoundex;

      }


      /// <summary>
      /// Summary of LongDirFix.
      /// </summary>
      /// <param name=sIncomming></param>
      /// <param name=iMax></param>
      /// 		
      public string LongDirFix(string sIncomming, int iMax)
      {
         int I;
         int LblLen;
         //			int StringLen;
         string TempString;

         TempString = sIncomming;
         LblLen = iMax;
         if (sf.Len(TempString) <= LblLen)
         {
            return TempString;
         }
         LblLen = LblLen - 6;
         for (I = sf.Len(TempString) - LblLen; I <= sf.Len(TempString); I++)
         {
            if (sf.Mid(TempString, I, 1) == "\\") break;
         } //
         return sf.Left(TempString, 3) + "..." + sf.Right(TempString, sf.Len(TempString) - (I - 1));
      }


      /// <summary>
      /// Summary of FindIndividual.
      /// </summary>
      /// <param name=iIndex></param>
      /// 		
      private void FindIndividual(int iIndex)
      {

         //			Family MyFamily;
         //			Child MyChild;
         string TheFamID;

         DateTime ActualDate;

         int iGedFileIndex;
         string sSoundex;
         string sSurname;
         string sGivenName;
         string sSex;
         string sBirthPlace;
         string sBirthDateText;
         object datBirthDate;
         string sDeathPlace;
         string sDeathDateText;
         object datDeathDate;
         string sFather;
         string sMother;
         string sSpouse;
         string sMarriagePlace;
         string sMarriageDateText;
         object datMarriageDate;


         iGedFileIndex = 0;
         sSoundex = "";
         sSurname = "";
         sGivenName = "";
         sSex = "";
         sBirthPlace = "";
         sBirthDateText = "";
         datBirthDate = "";
         sDeathPlace = "";
         sDeathDateText = "";
         datDeathDate = "";
         sFather = "";
         sMother = "";
         sSpouse = "";
         sMarriagePlace = "";
         sMarriageDateText = "";
         datMarriageDate = "";


         //sFileName = sFile
         iGedFileIndex = iIndex;
         sSurname = sf.UCase(MyIndividuals[iIndex].Surname);
         sSoundex = GetSoundexCode((MyIndividuals[iIndex].Surname));
         sGivenName = MyIndividuals[iIndex].Forenames;
         if (MyIndividuals[iIndex].Suffix != "")
         {
            sGivenName = sGivenName + "," + MyIndividuals[iIndex].Suffix;
         }
         //sGivenName = sGivenName;
         sSex = MyIndividuals[iIndex].Sex;

         //birth info
         if (MyIndividuals[iIndex].BirthDateText != "" && MyIndividuals[iIndex].BirthDateText != Privacy)
         {
            sBirthDateText = MyIndividuals[iIndex].BirthDateText;
            sBirthPlace = MyIndividuals[iIndex].BirthPlace;
            ActualDate = sf.DateValue(MyIndividuals[iIndex].BirthDateText);
            if (ActualDate.Year != 1)
            {
               datBirthDate = ActualDate.Year;
               ActualDate = new DateTime();
            }
         }
         else if (MyIndividuals[iIndex].BirthDateText == Privacy)
         {
            sBirthDateText = Privacy;
         }

         //death info
         if (MyIndividuals[iIndex].DeathDateText != "" && MyIndividuals[iIndex].DeathDateText != Privacy)
         {
            sDeathDateText = MyIndividuals[iIndex].DeathDateText;
            sDeathPlace = MyIndividuals[iIndex].DeathPlace;
            ActualDate = sf.DateValue(MyIndividuals[iIndex].DeathDateText);
            if (ActualDate.Year != 1)
            {
               datDeathDate = ActualDate.Year;
               ActualDate = new DateTime();
            }
         }
         else if (MyIndividuals[iIndex].DeathDateText == Privacy)
         {
            sDeathDateText = Privacy;
         }

         //get spouse and marriage information
         switch (MyIndividuals[iIndex].Sex)
         {
            case "M":
               foreach (Family family in MyFamilies)
               {
                  if (MyIndividuals[iIndex].ID == family.Husband)
                  {
                     sSpouse = "";
                     if (family.Wife != "?")
                     {
                        sSpouse = MyIndividuals[family.Wife].Forenames;
                        sSpouse = sSpouse + " " + sf.UCase(MyIndividuals[family.Wife].Surname);
                        if (MyIndividuals[family.Wife].Suffix != "")
                        {
                           sSpouse = sSpouse + ", " + MyIndividuals[family.Wife].Suffix;
                        }
                     }
                     //sSpouse = sSpouse;

                     if (family.MarriageDateText != Privacy)
                     {
                        sMarriagePlace = family.MarriagePlace;
                        sMarriageDateText = family.MarriageDateText;
                        ActualDate = sf.DateValue(family.MarriageDateText);
                        if (ActualDate.Year != 1)
                        {
                           datMarriageDate = ActualDate.Year;
                           ActualDate = new DateTime();
                        }
                     }
                     else
                     {
                        sMarriageDateText = Privacy;
                     }
                     break;
                  }
               } // family
               break;
            case "F":
               foreach (Family family in MyFamilies)
               {
                  if (MyIndividuals[iIndex].ID == family.Wife)
                  {
                     sSpouse = "";
                     if (family.Husband != "?")
                     {
                        sSpouse = MyIndividuals[family.Husband].Forenames;
                        sSpouse = sSpouse + " " + sf.UCase(MyIndividuals[family.Husband].Surname);
                        if (MyIndividuals[family.Husband].Suffix != "")
                        {
                           sSpouse = sSpouse + ", " + MyIndividuals[family.Husband].Suffix;
                        }
                     }
                     //sSpouse = sSpouse;
                     if (family.MarriageDateText != Privacy)
                     {
                        sMarriagePlace = family.MarriagePlace;
                        sMarriageDateText = family.MarriageDateText;
                        ActualDate = sf.DateValue(family.MarriageDateText);
                        if (ActualDate.Year != 1)
                        {
                           datMarriageDate = ActualDate.Year;
                           ActualDate = new DateTime();
                        }
                     }
                     else
                     {
                        sMarriageDateText = Privacy;
                     }
                     break;
                  }
               } // MyFamily
               break;
         }
         //================
         //get info on parents
         TheFamID = FindIndFamily((MyIndividuals[iIndex].ID));
         if (TheFamID != "")
         {
            //he is in this family
            if (MyFamilies[TheFamID].Husband != "?")
            {
               sFather = MyIndividuals[MyFamilies[TheFamID].Husband].Forenames + " " + MyIndividuals[MyFamilies[TheFamID].Husband].Surname;
               sFather = sf.Trim(sFather);
            }
            if (MyFamilies[TheFamID].Wife != "?")
            {
               sMother = MyIndividuals[MyFamilies[TheFamID].Wife].Forenames + " " + MyIndividuals[MyFamilies[TheFamID].Wife].Surname;
               sMother = sf.Trim(sMother);
            }
         }

      }


      /// <summary>
      /// Summary of FindIndFamily.
      /// </summary>
      /// <param name=sIndID></param>
      /// 		
      private string FindIndFamily(string sIndID)
      {
         //use a binary search to find the child family id for this individual
         //returns the child//s family id
         int MinIndex;
         int MaxIndex;
         string sSearch;
         int iFound;

         MinIndex = 1;
         MaxIndex = MyChildren.Count;
         sSearch = sIndID;

         iFound = BSearchChildren(MinIndex, MaxIndex, sSearch);

         if (iFound > 0)
         {
            return MyChildren[iFound].FamilyID;
         }
         else
         {
            return "";
         }

      }


      /// <summary>
      /// Summary of BSearchChildren.
      /// </summary>
      /// <param name=First></param>
      /// <param name=Last></param>
      /// <param name=Value></param>
      /// 		
      private int BSearchChildren(int First, int Last, string Value)
      {
         //perform a recursive binary search for the child//s family id
         int MidList;

         //is the middle one the one we are looking for?
         MidList = (int)((First + Last) / 2);
         if (MyChildren[MidList].ChildID == Value)
         {
            return MidList;
         }

         //check the first
         if (MyChildren[First].ChildID == Value)
         {
            return First;
         }

         //and the last
         if (MyChildren[Last].ChildID == Value)
         {
            return Last;
         }

         //if there is only one left in the list then exit
         if (MidList == First || MidList == Last)
         {
            return -1;
         }

         //half the list according to the Value//s position
         if (System.Convert.ToInt32(Value) < System.Convert.ToInt32(MyChildren[MidList].ChildID))
         {
            Last = MidList;
         }
         else
         {
            First = MidList + 1;
         }

         return BSearchChildren(First, Last, Value);

      }


      /// <summary>
      /// Summary of SetChildrenFlag.
      /// </summary>
      /// 		
      private void SetChildrenFlag()
      {
         int iNumFams;
         int iFamCount;
         string FamRefID;

         iNumFams = MyFamilies.Count;
         for (iFamCount = 0; iFamCount <= iNumFams - 1; iFamCount++)
         {
            if (_didCancel) return;
            FamRefID = MyFamilies[iFamCount].ID;
            foreach (Child child in MyChildren)
            {
               if (_didCancel) return;
               if (child.FamilyID == FamRefID)
               {
                  MyFamilies[iFamCount].HasChildren = true;
                  break;
               }
            }	 // child
         } // iFamCount
         return;
      }


      /// <summary>
      /// Summary of SetOwnFamilyFlag.
      /// </summary>
      /// 		
      private void SetOwnFamilyFlag()
      {

         int iChildCnt = 0;
         int iNumChildren;

         iNumChildren = MyChildren.Count;


         foreach (Child child in MyChildren)
         {
            if (_didCancel) return;
            iChildCnt = iChildCnt + 1;

            foreach (Family family in MyFamilies)
            {
               if (_didCancel) return;
               if (MyIndividuals[child.ChildID].Sex == "M")
               {
                  if (child.ChildID == family.Husband)
                  {
                     MyIndividuals[child.ChildID].HasOwnFamily = true;
                     break;
                  }
               }
               else
               {
                  if (child.ChildID == family.Wife)
                  {
                     MyIndividuals[child.ChildID].HasOwnFamily = true;
                     break;
                  }
               }
            } // family
         } // child

         return;
      }


      /// <summary>
      /// Summary of GetFilePart.
      /// </summary>
      /// <param name=sFullPath></param>
      /// <param name=iOption></param>
      /// 		
      private string GetFilePart(string sFullPath, short iOption)
      {
         string sDriveLetter;
         string sDirPath;
         string sFileName;
         string sExtension;
         int iPathLength;
         int iOffset;
         int iThisLength;
         bool bFileNameFound = false;

         sDriveLetter = "";
         sDirPath = "";
         sFileName = "";
         sExtension = "";

         if (sf.Mid(sFullPath, 2, 1) == ":")
         { // Find the drive letter.
            sDriveLetter = sf.Left(sFullPath, 2);
            sFullPath = sf.Mid(sFullPath, 3);
         }
         iPathLength = sf.Len(sFullPath);
         for (iOffset = iPathLength; iOffset <= 1; iOffset--)
         { // Find the next delimiter.
            switch (sf.Mid(sFullPath, iOffset, 1))
            {
               case ".":// This indicates either an extension or a . or a ..;
                  iThisLength = sf.Len(sFullPath) - iOffset;
                  if (iThisLength >= 1 && iThisLength <= 3)
                  { // sExtension
                     sExtension = sf.Mid(sFullPath, iOffset, iThisLength + 1);
                  }
                  sFullPath = sf.Left(sFullPath, iOffset - 1);
                  break;
               case "\\": // This indicates a path delimiter.;
                  iThisLength = sf.Len(sFullPath) - iOffset;
                  if (iThisLength >= 1 && iThisLength <= 8)
                  { // Filename
                     sFileName = sf.Mid(sFullPath, iOffset + 1, iThisLength);
                     sFullPath = sf.Left(sFullPath, iOffset);
                     bFileNameFound = true;
                     break;
                  }
                  break;
               default:
                  break;
            }
         } // iOffset

         if (bFileNameFound == false)
         {
            sFileName = sFullPath;
         }
         else
         {
            sDirPath = sFullPath;
         } // Print to form for display.

         switch (iOption)
         {
            case GET_DRIVE:
               return sDriveLetter;
            case GET_DIRECTORY:
               return sDirPath;
            case GET_FILENAME:
               return sFileName;
            case GET_EXTENSION:
               return sExtension;
            default:
               return "";
         }

      }


      /// <summary>
      /// Summary of FixEstLoc.
      /// </summary>
      /// <param name=sLocation></param>
      /// 		
      private string FixEstLoc(string sLocation)
      {
         //strips off "< >" from an estimated location - see Legacy 3.0

         try
         {

            string sTemp;


            sTemp = sf.Trim(sLocation);

            if (sf.Left(sTemp, 1) == "<" && sf.Right(sTemp, 1) == ">")
            {
               sTemp = sf.Right(sTemp, sf.Len(sTemp) - 1);
               sTemp = sf.Left(sTemp, sf.Len(sTemp) - 1);
               sTemp = "&lt;" + sTemp + "&gt;";
            }

            return sTemp;
         }
         catch
         {

            return sLocation;
         }
      }

      /// <summary>
      /// Summary of GetTimeLineEvents.
      /// </summary>
      /// 		
      private void GetTimeLineEvents()
      {
         //added in 3.01
         int iCnt;
         int jCnt;
         DateTime dtActualDate = new DateTime();
         int iYear = 0;
         int iTotItems;
         string sDateText;
         string sEventDetails;
         string sHusband;
         string sWife;
         string sName;
         int iNumEvents;
         string sEventText;
         bool bIsAbout = false;
         int iEstimateStyle = 0;
         string sColorCode;
         string sLinkPage;
         string sTemp;
         int iPageNum;
         char Q = '"';

         MyTimeLineEntries = new TimeLineEntries();

         //marriages
         iTotItems = MyFamilies.Count;
         if (iTotItems != 0)
         {
            for (iCnt = 0; iCnt <= iTotItems - 1; iCnt++)
            {
               sEventDetails = "";
               //MainForm.pbFile.value = (iCnt / iTotItems) * 100
               sDateText = MyFamilies[iCnt].MarriageDateText;
               Tools.GetDates(sDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);

               if (iYear <= m_cfg.ChronoCutOff && iYear != 0)
               {
                  if (MyFamilies[iCnt].Husband != "?")
                  {
                     sHusband = MyIndividuals[MyFamilies[iCnt].Husband].Forenames + " " + MyIndividuals[MyFamilies[iCnt].Husband].Surname;
                     if (MyIndividuals[MyFamilies[iCnt].Husband].Suffix != "")
                     {
                        sHusband = sHusband + ", " + MyIndividuals[MyFamilies[iCnt].Husband].Suffix;
                     }
                  }
                  else
                  {
                     sHusband = "?";
                  }

                  if (MyFamilies[iCnt].Wife != "?")
                  {
                     sWife = MyIndividuals[MyFamilies[iCnt].Wife].Forenames + " " + MyIndividuals[MyFamilies[iCnt].Wife].Surname;
                     if (MyIndividuals[MyFamilies[iCnt].Wife].Suffix != "")
                     {
                        sWife = sWife + ", " + MyIndividuals[MyFamilies[iCnt].Wife].Suffix;
                     }
                  }
                  else
                  {
                     sWife = "?";
                  }

                  //@F5@ - example family id - then numeric portion equals the page number
                  sTemp = sf.Right(MyFamilies[iCnt].ID, sf.Len(MyFamilies[iCnt].ID) - 2);
                  iPageNum = System.Convert.ToInt32(sf.Left(sTemp, sf.Len(sTemp) - 1));
                  sLinkPage = m_cfg.FamFilePrefix + iPageNum.ToString("000") + ".html";

                  if (sHusband != "?")
                  {
                     if (m_cfg.ChronoLinks == true) sEventDetails = "<a href=" + Q + sLinkPage + Q + ">";
                     sEventDetails = sEventDetails + sHusband;
                     if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "</a>";
                  }
                  else
                  {
                     sEventDetails = sHusband;
                  }
                  sEventDetails = sEventDetails + " and ";
                  if (sWife != "?")
                  {
                     if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "<a href=" + Q + sLinkPage + Q + ">";
                     sEventDetails = sEventDetails + sWife;
                     if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "</a>";
                  }
                  else
                  {
                     sEventDetails = sEventDetails + sWife;
                  }
                  sEventDetails = sEventDetails + " are married";

                  if (MyFamilies[iCnt].MarriagePlace != "")
                  {
                     sEventDetails = sEventDetails + " in " + MyFamilies[iCnt].MarriagePlace;
                  }
                  else
                  {
                     sEventDetails = sEventDetails + ".";
                  }
                  if (iYear != 0 && (sHusband != "?" || sWife != "?"))
                  {
                     sColorCode = "Pink";
                     MyTimeLineEntries.Add(iYear, dtActualDate, sEventDetails, bIsAbout, sColorCode, iEstimateStyle, "M" + MyFamilies[iCnt].ID);
                  }
               }
            } // iCnt
         }

         //births
         iTotItems = MyIndividuals.Count;
         if (iTotItems != 0)
         {
            for (iCnt = 0; iCnt <= iTotItems - 1; iCnt++)
            {
               sEventDetails = "";
               sDateText = MyIndividuals[iCnt].BirthDateText;
               Tools.GetDates(sDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);

               if (iYear <= m_cfg.ChronoCutOff && iYear != 0)
               {
                  sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
                  if (MyIndividuals[iCnt].Suffix != "")
                  {
                     sName = sName + ", " + MyIndividuals[iCnt].Suffix;
                  }
                  if (m_cfg.ChronoLinks == true) sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
                  sEventDetails = sEventDetails + sName;
                  if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "</a>";
                  sEventDetails = sEventDetails + " is born";
                  if (MyIndividuals[iCnt].BirthPlace != "")
                  {
                     sEventDetails = sEventDetails + " in " + MyIndividuals[iCnt].BirthPlace;
                  }
                  else
                  {
                     sEventDetails = sEventDetails + ".";
                  }
                  if (iYear != 0 && MyIndividuals[iCnt].Surname != "")
                  {
                     sColorCode = "Green";
                     MyTimeLineEntries.Add(iYear, dtActualDate, sEventDetails, bIsAbout, sColorCode, iEstimateStyle, "B" + MyIndividuals[iCnt].ID);
                  }
               }
            } // iCnt
         }

         //deaths
         iTotItems = MyIndividuals.Count;
         if (iTotItems != 0)
         {
            for (iCnt = 0; iCnt <= iTotItems - 1; iCnt++)
            {
               sEventDetails = "";
               sDateText = MyIndividuals[iCnt].DeathDateText;
               Tools.GetDates(sDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);

               if (iYear <= m_cfg.ChronoCutOff && iYear != 0)
               {
                  sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
                  if (MyIndividuals[iCnt].Suffix != "")
                  {
                     sName = sName + ", " + MyIndividuals[iCnt].Suffix;
                  }

                  if (m_cfg.ChronoLinks == true) sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
                  sEventDetails = sEventDetails + sName;
                  if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "</a>";
                  sEventDetails = sEventDetails + " dies";
                  if (MyIndividuals[iCnt].DeathPlace != "")
                  {
                     sEventDetails = sEventDetails + " in " + MyIndividuals[iCnt].DeathPlace;
                  }
                  else
                  {
                     sEventDetails = sEventDetails + ".";
                  }
                  if (iYear != 0 && MyIndividuals[iCnt].Surname != "")
                  {
                     sColorCode = "Red";
                     MyTimeLineEntries.Add(iYear, dtActualDate, sEventDetails, bIsAbout, sColorCode, iEstimateStyle, "D" + MyIndividuals[iCnt].ID);
                  }
               }
            } // iCnt
         }

         //life events
         iTotItems = MyIndividuals.Count;
         if (iTotItems != 0)
         {
            for (iCnt = 0; iCnt <= iTotItems - 1; iCnt++)
            {
               iNumEvents = MyIndividuals[iCnt].LifeEvents.Count;
               if (iNumEvents != 0)
               {
                  for (jCnt = 0; jCnt <= iNumEvents - 1; jCnt++)
                  {
                     if (MyIndividuals[iCnt].LifeEvents[jCnt].EventType == LifeEvent.EventTypes.etBirth ||
                        MyIndividuals[iCnt].LifeEvents[jCnt].EventType == LifeEvent.EventTypes.etDeath) continue;

                     sEventDetails = "";
                     sDateText = MyIndividuals[iCnt].LifeEvents[jCnt].EventDateString;
                     Tools.GetDates(sDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);

                     if (iYear <= m_cfg.ChronoCutOff && iYear != 0)
                     {
                        sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
                        if (MyIndividuals[iCnt].Suffix != "")
                        {
                           sName = sName + ", " + MyIndividuals[iCnt].Suffix;
                        }

                        sEventText = MyIndividuals[iCnt].LifeEvents[jCnt].EventText;
                        if (sf.Left(sEventText, 5) == "Note ")
                        {
                           sEventText = sf.Right(sEventText, sf.Len(sEventText) - 5);
                        }

                        if (m_cfg.ChronoLinks == true) sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
                        sEventDetails = sEventDetails + sName;
                        if (m_cfg.ChronoLinks == true) sEventDetails = sEventDetails + "</a>";

                        sEventDetails = sEventDetails + "&nbsp;-&nbsp;" + sEventText;

                        if (MyIndividuals[iCnt].LifeEvents[jCnt].EventPlace != "")
                        {
                           sEventDetails = sEventDetails + " (" + MyIndividuals[iCnt].LifeEvents[jCnt].EventPlace + ")";
                        }
                        else
                        {
                           sEventDetails = sEventDetails + ".";
                        }
                        if (iYear != 0 && MyIndividuals[iCnt].Surname != "")
                        {
                           switch (MyIndividuals[iCnt].LifeEvents[jCnt].EventType)
                           {
                              case LifeEvent.EventTypes.etBaptism:
                                 goto case LifeEvent.EventTypes.etChristening;
                              case LifeEvent.EventTypes.etChristening:
                                 sColorCode = "Gold";
                                 break;
                              case LifeEvent.EventTypes.etBurial:
                                 goto case LifeEvent.EventTypes.etCremation;
                              case LifeEvent.EventTypes.etCremation:
                                 sColorCode = "DARKMAGENTA";
                                 break;
                              default:
                                 sColorCode = "Blue";
                                 break;
                           }
                           MyTimeLineEntries.Add(iYear, dtActualDate, sEventDetails, bIsAbout, sColorCode, iEstimateStyle, MyIndividuals[iCnt].LifeEvents[jCnt].ID);
                        }
                     }
                  } // jCnt
               }
            } // iCnt
         }

      }


      /// <summary>
      /// Summary of GetMarriageLink.
      /// </summary>
      /// <param name=sLink1></param>
      /// <param name=sLink2></param>
      /// 		
      private string GetMarriageLink(string sLink1, string sLink2)
      {
         int Mrin1;
         int Mrin2;
         string sTemp;
         int iWhereDot;

         sTemp = sf.Right(sLink1, sf.Len(sLink1) - 3);
         iWhereDot = sf.InStr(sTemp, ".");
         if (iWhereDot != 0)
         {
            sTemp = sf.Left(sTemp, iWhereDot);
            Mrin1 = System.Convert.ToInt32(sTemp);
         }
         else
         {
            Mrin1 = 9999;
         }

         sTemp = sf.Right(sLink2, sf.Len(sLink2) - 3);
         iWhereDot = sf.InStr(sTemp, ".");
         if (iWhereDot != 0)
         {
            sTemp = sf.Left(sTemp, iWhereDot);
            Mrin2 = System.Convert.ToInt32(sTemp);
         }
         else
         {
            Mrin2 = 9999;
         }

         if (Mrin1 < Mrin2)
         {
            return sLink1;
         }
         else
         {
            return sLink2;
         }

      }


      /// <summary>
      /// Summary of ReverseLocation.
      /// </summary>
      /// <param name=sLocation></param>
      /// 		
      private string ReverseLocation(string sLocation)
      {
         int iCnt;
         string sTemp = "";
         int iStart;
         bool bIsEstimate = false;
         string sThisLocation;
         int X;

         try
         {


            if (sf.Trim(sLocation) == "")
            {
               return "";
            }

            sThisLocation = sf.Trim(sLocation);

            if (sf.Left(sThisLocation, 1) == "[" || sf.Left(sThisLocation, 1) == "<")
            {
               sThisLocation = sf.Mid(sThisLocation, 2, sf.Len(sThisLocation) - 2);
               bIsEstimate = true;
            }

            if (sf.Left(sThisLocation, 1) == ",") sThisLocation = sf.Right(sThisLocation, sf.Len(sThisLocation) - 1);
            if (sf.Right(sThisLocation, 1) == ",") sThisLocation = sf.Left(sThisLocation, sf.Len(sThisLocation) - 1);

            iStart = sf.Len(sThisLocation) + 1;
            for (iCnt = sThisLocation.Length; iCnt >= 1; iCnt--)
            {
               if (sf.Mid(sThisLocation, iCnt, 1) == ",")
               {
                  if (sf.Len(sTemp) != 0) sTemp = sTemp + ", ";
                  sTemp = sTemp + sf.Trim(sf.Mid(sThisLocation, iCnt + 1, iStart - iCnt - 1));
                  iStart = iCnt;
               }
            } // iCnt
            if (sf.Len(sTemp) != 0)
            {
               X = sf.InStr(sThisLocation, ", ");
               if (X != 0)
               {
                  sTemp = sTemp + ", " + sf.Left(sThisLocation, X - 1);
               }
               else
               {
                  sTemp = sThisLocation;
               }
            }
            else
            {
               sTemp = sThisLocation;
            }
            sTemp = sf.Trim(sTemp);
            if (bIsEstimate == true && sTemp != "")
            {
               sTemp = "[" + sTemp + "]";
            }

            return sTemp.Trim();
         }
         catch
         {
            return sLocation;
         }
      }


      /// <summary>
      /// Summary of StripChar.
      /// </summary>
      /// <param name=sString></param>
      /// <param name=sChar></param>
      /// <param name=bReplaceWithSpace></param>
      /// 		
      private string StripChar(string sString, string sChar, bool bReplaceWithSpace)
      {
         string tempStr1;
         string tempStr2;

         tempStr1 = sString;
         tempStr1 = sString.Replace(sChar, " ");

         if (!bReplaceWithSpace)
         {
            //remove the spaces
            tempStr2 = tempStr1.Replace(" ", "");
            tempStr1 = tempStr2;
         }

         return tempStr1;
      }


      /// <summary>
      /// Cleans up the occupation title
      /// </summary>
      /// <param name=sOccupation></param>
      /// 		
      private string FixOccupation(string sOccupation)
      {

         string sTemp;
         int iCnt;
         string sTest;

         sOccupation = sf.Trim(sOccupation);
         sTest = "OCCUPATION: ";
         if (sf.UCase(sf.Left(sOccupation, sf.Len(sTest))) == sTest)
         {
            sOccupation = sf.Right(sOccupation, sf.Len(sOccupation) - sf.Len(sTest));
         }

         sTemp = sf.Trim(sOccupation);

         //strip off any articles such as a, an, or the
         if (sf.UCase(sf.Left(sOccupation, 2)) == "A ")
         {
            sTemp = sf.Right(sOccupation, sf.Len(sOccupation) - 2);
         }

         if (sf.UCase(sf.Left(sOccupation, 3)) == "AN ")
         {
            sTemp = sf.Right(sOccupation, sf.Len(sOccupation) - 3);
         }

         if (sf.UCase(sf.Left(sOccupation, 4)) == "THE ")
         {
            sTemp = sf.Right(sOccupation, sf.Len(sOccupation) - 4);
         }

         //capitalize the first letter of each word in the occupation title
         StringBuilder sb = new StringBuilder(sTemp);

         for (iCnt = 0; iCnt <= sb.Length - 1; iCnt++)
         {
            if (iCnt == 0)
            {
               sb[0] = System.Convert.ToChar(sb[0].ToString().ToUpper());
            }
            else if (sb[iCnt - 1] == ' ')
            {
               sb[iCnt] = System.Convert.ToChar(sb[iCnt].ToString().ToUpper());
            }
         } // iCnt

         sTemp = sb.ToString();

         return sTemp;

      }


      /// <summary>
      /// Summary of GetMoreStats.
      /// </summary>
      /// 		
      private MoreStats GetMoreStats()
      {

         MoreStats moreStats = new MoreStats();
         int NumFamilies = MyFamilies.Count;
         int iFamCnt = 0;
         string FamRefId = "0";
         double childCount = 0;
         Statistics myStatistics;
         DateTime dtActualDate = new DateTime();
         DateTime emptyDate = new DateTime();
         int iYear = 0;
         bool bIsAbout = false;
         int iEstimateStyle = 0;
         int monthNumber;
         int yearNumber;
         int birthYear;
         int deathYear;

         myStatistics = new Statistics();
         for (iFamCnt = 0; iFamCnt <= NumFamilies - 1; iFamCnt++)
         {

            FamRefId = MyFamilies[iFamCnt].ID;
            foreach (Child child in MyChildren)
            {
               if (child.FamilyID == FamRefId)
               {
                  childCount += 1;
               }
            } //
            myStatistics.Add(childCount);
         } //
         moreStats.AvgNumChildrenPerFamily = myStatistics.Mean;


         myStatistics = new Statistics();
         foreach (Individual individual in MyIndividuals)
         {
            birthYear = 0;
            deathYear = 0;
            if (individual.BirthDateText.Length != 0)
            {
               Tools.GetDates(individual.BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
               birthYear = iYear;

               if (dtActualDate != emptyDate)
               {
                  monthNumber = dtActualDate.Month;
                  switch (monthNumber)
                  {
                     case 1: moreStats.NumBornInJAN += 1; break;
                     case 2: moreStats.NumBornInFEB += 1; break;
                     case 3: moreStats.NumBornInMAR += 1; break;
                     case 4: moreStats.NumBornInAPR += 1; break;
                     case 5: moreStats.NumBornInMAY += 1; break;
                     case 6: moreStats.NumBornInJUN += 1; break;
                     case 7: moreStats.NumBornInJUL += 1; break;
                     case 8: moreStats.NumBornInAUG += 1; break;
                     case 9: moreStats.NumBornInSEP += 1; break;
                     case 10: moreStats.NumBornInOCT += 1; break;
                     case 11: moreStats.NumBornInNOV += 1; break;
                     case 12: moreStats.NumBornInDEC += 1; break;
                  }
               }

               yearNumber = iYear;
               if (yearNumber != 0)
               {

                  if (yearNumber < 1600)
                  {
                     moreStats.CountBornBefore1600 += 1;
                  }
                  else if (yearNumber < 1700)
                  {
                     moreStats.CountBorn17thCentury += 1;
                  }
                  else if (yearNumber < 1800)
                  {
                     moreStats.CountBorn18thCentury += 1;
                  }
                  else if (yearNumber < 1900)
                  {
                     moreStats.CountBorn19thCentury += 1;
                  }
                  else if (yearNumber < 2000)
                  {
                     moreStats.CountBorn20thCentury += 1;
                  }
               }

            }

            if (individual.DeathDateText.Length != 0)
            {
               Tools.GetDates(individual.DeathDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
               deathYear = iYear;
               if (dtActualDate != emptyDate)
               {
                  monthNumber = dtActualDate.Month;
                  switch (monthNumber)
                  {
                     case 1: moreStats.NumDiedInJAN += 1; break;
                     case 2: moreStats.NumDiedInFEB += 1; break;
                     case 3: moreStats.NumDiedInMAR += 1; break;
                     case 4: moreStats.NumDiedInAPR += 1; break;
                     case 5: moreStats.NumDiedInMAY += 1; break;
                     case 6: moreStats.NumDiedInJUN += 1; break;
                     case 7: moreStats.NumDiedInJUL += 1; break;
                     case 8: moreStats.NumDiedInAUG += 1; break;
                     case 9: moreStats.NumDiedInSEP += 1; break;
                     case 10: moreStats.NumDiedInOCT += 1; break;
                     case 11: moreStats.NumDiedInNOV += 1; break;
                     case 12: moreStats.NumDiedInDEC += 1; break;
                  }
               }
            }

            if (birthYear != 0 && deathYear != 0)
            {
               myStatistics.Add((double)deathYear - birthYear);
            }
         } //

         moreStats.AvgAgeAtDeath = myStatistics.Mean;

         return moreStats;
      }


      /// <summary>
      /// Summary of CreateGUIDKey.
      /// </summary>
      /// 		
      private string CreateGUIDKey()
      {
         Guid myGUID = Guid.NewGuid();
         return myGUID.ToString();
      }


      /// <summary>
      /// Summary of GetOtherLink.
      /// </summary>
      /// <param name=sThisLink></param>
      /// <param name=iCnt></param>
      /// <param name=bIsBook></param>
      /// 		
      private string GetOtherLink(string sThisLink, int iCnt, bool bIsBook)
      {
         string sTemp;
         string sOtherLink;
         string sChHusband;
         string sChWife;
         string sChTitle;

         char QUOTE = '"';

         if (iCnt == 0)
         {
            sTemp = "See ";
         }
         else
         {
            sTemp = " OR ";
         }

         sOtherLink = sThisLink;
         sOtherLink = sf.Right(sOtherLink, sf.Len(sOtherLink) - 2);
         sOtherLink = sf.Left(sOtherLink, sf.Len(sOtherLink) - 1);
         sOtherLink = System.Convert.ToInt32(sOtherLink).ToString("000");
         if (bIsBook == true)
         {
            sOtherLink = "#F-" + sOtherLink;
         }
         else
         {
            sOtherLink = m_cfg.FamFilePrefix + sOtherLink + ".html";
         }

         sTemp = sTemp + "<A HREF=" + QUOTE + sOtherLink + QUOTE + ">";

         //the husband
         if (MyFamilies[sThisLink].Husband != "?")
         {
            sChHusband = MyIndividuals[MyFamilies[sThisLink].Husband].Forenames + " " + MyIndividuals[MyFamilies[sThisLink].Husband].Surname;
            if (MyIndividuals[MyFamilies[sThisLink].Husband].Suffix != "")
            {
               sChHusband = sChHusband + ", " + MyIndividuals[MyFamilies[sThisLink].Husband].Suffix;
            }
         }
         else
         {
            sChHusband = "?";
         }

         //the wife
         if (MyFamilies[sThisLink].Wife != "?")
         {
            sChWife = MyIndividuals[MyFamilies[sThisLink].Wife].Forenames + " " + MyIndividuals[MyFamilies[sThisLink].Wife].Surname;
            if (MyIndividuals[MyFamilies[sThisLink].Wife].Suffix != "")
            {
               sChWife = sChWife + ", " + MyIndividuals[MyFamilies[sThisLink].Wife].Suffix;
            }
         }
         else
         {
            sChWife = "?";
         }

         //title of web page that we are linking to
         sChTitle = sChHusband + " &amp; " + sChWife;

         sTemp = sTemp + sChTitle;
         sTemp = sTemp + "</A>";
         return sTemp;
      }


      /// <summary>
      /// Summary of GetOtherMarriages.
      /// </summary>
      /// <param name=sThisIndId></param>
      /// <param name=sThisFamId></param>
      /// 		
      private ArrayList GetOtherMarriages(string sThisIndId, string sThisFamId)
      {
         int iNumFound = -1;

         const int MAX_NUM_FOUND = 32; //some ridiculous number

         ArrayList aryOtherFams = new ArrayList();

         try
         {
            foreach (Family family in MyFamilies)
            {
               if (iNumFound == MAX_NUM_FOUND - 1) break;
               if (family.Husband == sThisIndId && family.ID != sThisFamId)
               {
                  iNumFound++;
                  aryOtherFams.Add(family.ID);
               }
               else if (family.Wife == sThisIndId && family.ID != sThisFamId)
               {
                  iNumFound++;
                  aryOtherFams.Add(family.ID);
               }
            } // family


         }
         catch
         {
            //empty catch
         }

         return aryOtherFams;

      }
      #endregion

      #region Methods For Estimating Dates
      //const for estimating dates
      private const int MAX_LIVING_AGE = 75;
      private const int MAX_BAPT_AGE = 10;
      private const int MAX_BURIAL_ELAPSED = 1;
      private const int MIN_MARR_AGE = 20;
      private const int MIN_CHILDBIRTH = 20;
      private const int MAX_CHILDBIRTH = 50;
      private const int ABT_EQUALS = 2;
      private const int MAX_AGE_DIFF = 10;
      private const int MAX_ITERATIONS = 5;
      private const int MIN_ALLOWED_YEAR = 0;

      public int MinAllowedYear
      {
         get
         {
            return MIN_ALLOWED_YEAR;
         }
      }

      /// <summary>
      /// Summary of EstimateBirthDates.
      /// </summary>
      /// 		
      public void EstimateBirthDates()
      {
         DateTime dtActualDate = new DateTime();
         int iYear = 0;
         bool bIsAbout = false;
         int iEstimateStyle = 0;
         string sFamKey;
         int iCnt;
         int iLoopCnt;

         FireStatusMessage("Performing date estimation.");
         for (iLoopCnt = 1; iLoopCnt <= MAX_ITERATIONS; iLoopCnt++)
         {
            Tools.SilentLogit("}: " + iLoopCnt.ToString());
            foreach (Individual individual in MyIndividuals)
            {
               if (individual.BirthDateText.Length == 0 || individual.DidEstimate == true)
               {
                  //minBirthYear = 0
                  //maxBirthYear = 9999

                  Tools.GetDates(individual.BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);

                  //do we have any dates for this indi?
                  Tools.GetDates(individual.BaptismDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                  if (iYear != 0)
                  {
                     individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MAX_BAPT_AGE);
                     individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear);
                     Tools.SilentLogit("Constraint 1:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                     individual.DidEstimate = true;
                  }

                  Tools.GetDates(individual.DeathDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                  if (iYear != 0)
                  {
                     individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MAX_LIVING_AGE);
                     individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear);
                     Tools.SilentLogit("Constraint 2:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                     individual.DidEstimate = true;
                  }

                  Tools.GetDates(individual.BurialDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                  if (iYear != 0)
                  {
                     individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MAX_LIVING_AGE);
                     individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear);
                     Tools.SilentLogit("Constraint 3:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                     individual.DidEstimate = true;
                  }

                  foreach (LifeEvent theLifeEvent in individual.LifeEvents)
                  {
                     Tools.GetDates(theLifeEvent.EventDateString, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                     if (iYear != 0)
                     {
                        if (iYear < individual.MinBirthYear)
                        {
                           individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear);
                           Tools.SilentLogit("Constraint 4:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                           individual.DidEstimate = true;
                        }
                        if (iYear > individual.MaxBirthYear)
                        {
                           individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear);
                           Tools.SilentLogit("Constraint 5:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                           individual.DidEstimate = true;
                        }
                     }
                  } //

                  //get dates for any spouses
                  if (individual.FamList.Count > 0)
                  {
                     for (iCnt = 0; iCnt <= individual.FamList.Count - 1; iCnt++)
                     {

                        //marriage date
                        Tools.GetDates(MyFamilies[individual.FamList[iCnt].FamId].MarriageDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                        if (iYear != 0)
                        {
                           if (individual.MinBirthYear > iYear)
                           {
                              individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MIN_MARR_AGE);
                              Tools.SilentLogit("Constraint 6:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                              individual.DidEstimate = true;
                           }
                           if (individual.MaxBirthYear > iYear)
                           {
                              individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear - MIN_MARR_AGE);
                              Tools.SilentLogit("Constraint 6a:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                              individual.DidEstimate = true;
                           }
                        }

                        //the spouses birth date
                        iYear = 0;

                        if (individual.Sex == "F")
                        {
                           if (MyFamilies[individual.FamList[iCnt].FamId].Husband != "?")
                           {
                              Tools.GetDates(MyIndividuals[MyFamilies[individual.FamList[iCnt].FamId].Husband].BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                           }
                        }
                        else
                        {
                           if (MyFamilies[individual.FamList[iCnt].FamId].Wife != "?")
                           {
                              Tools.GetDates(MyIndividuals[MyFamilies[individual.FamList[iCnt].FamId].Wife].BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                           }
                        }
                        if (iYear != 0)
                        {
                           if (individual.MinBirthYear > iYear)
                           {
                              individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MIN_MARR_AGE);
                              Tools.SilentLogit("Constraint 7:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                              individual.DidEstimate = true;
                           }
                           if (individual.MaxBirthYear > iYear)
                           {
                              individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear + MAX_AGE_DIFF);
                              individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MAX_AGE_DIFF);
                              Tools.SilentLogit("Constraint 8:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                              individual.DidEstimate = true;
                           }

                           //the spouse//s death date
                           if (individual.Sex == "F")
                           {
                              Tools.GetDates(MyIndividuals[MyFamilies[individual.FamList[iCnt].FamId].Husband].DeathDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                           }
                           else
                           {
                              Tools.GetDates(MyIndividuals[MyFamilies[individual.FamList[iCnt].FamId].Wife].DeathDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                           }
                           if (iYear != 0)
                           {
                              if (individual.MaxBirthYear > iYear)
                              {
                                 individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear - MIN_MARR_AGE);
                                 individual.DidEstimate = true;
                                 Tools.SilentLogit("Constraint 8a:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                              }
                           }

                        }

                        //do the children here....
                        //now examine the children//s birth dates
                        foreach (Child ch in MyChildren)
                        {
                           if (ch.FamilyID == individual.FamList[iCnt].FamId)
                           {
                              Tools.GetDates(MyIndividuals[ch.ChildID].BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                              if (iYear != 0)
                              {
                                 if (individual.MinBirthYear > iYear)
                                 {
                                    individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MIN_CHILDBIRTH);
                                    Tools.SilentLogit("Constraint 14:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                                    individual.DidEstimate = true;
                                 }
                                 if (individual.MinBirthYear < iYear - MAX_LIVING_AGE)
                                 {
                                    individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MIN_CHILDBIRTH);
                                    Tools.SilentLogit("Constraint 14a:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                                    individual.DidEstimate = true;
                                 }
                                 if (individual.MaxBirthYear > iYear - MIN_MARR_AGE)
                                 {
                                    individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear - MIN_CHILDBIRTH);
                                    Tools.SilentLogit("Constraint 15:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                                    individual.DidEstimate = true;
                                 }
                                 if (individual.MaxBirthYear < iYear - MAX_LIVING_AGE)
                                 {
                                    individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear - MIN_CHILDBIRTH);
                                    Tools.SilentLogit("Constraint 15a:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                                    individual.DidEstimate = true;
                                 }
                              }
                           }
                        } //

                     } //
                  }

                  //get dates for parents
                  Child child;
                  if (individual.FamilyID.Length != 0)
                  {
                     sFamKey = individual.FamilyID + individual.ID;

                     try
                     {
                        child = MyChildren[sFamKey];
                     }
                     catch
                     {
                        child = null;
                     }

                     if (child == null)
                     {
                        if (MyFamilies[child.FamilyID].Husband != "?")
                        {
                           //find dates regarding father
                           Tools.GetDates(MyIndividuals[MyFamilies[child.FamilyID].Husband].BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                           if (iYear != 0)
                           {
                              if (individual.MinBirthYear < iYear)
                              {
                                 //adjust based on father//s birth year
                                 individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear + MIN_MARR_AGE);
                                 Tools.SilentLogit("Constraint 9:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                                 individual.DidEstimate = true;
                              }
                           }
                           Tools.GetDates(MyIndividuals[MyFamilies[child.FamilyID].Husband].DeathDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                           if (iYear != 0)
                           {
                              if (individual.MaxBirthYear > iYear)
                              {
                                 individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear - 1);
                                 Tools.SilentLogit("Constraint 10:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                                 individual.DidEstimate = true;
                              }
                           }
                        }
                        if (MyFamilies[child.FamilyID].Wife != "?")
                        {
                           //find dates regarding mother
                           Tools.GetDates(MyIndividuals[MyFamilies[child.FamilyID].Wife].BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                           if (iYear != 0)
                           {
                              if (individual.MinBirthYear < iYear)
                              {
                                 //adjust based on mother//s birth year
                                 individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear + MIN_CHILDBIRTH);
                                 Tools.SilentLogit("Constraint 11:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                                 individual.DidEstimate = true;
                              }
                              if (individual.MaxBirthYear > iYear + MAX_CHILDBIRTH)
                              {
                                 //adjust based on mother//s birth year
                                 individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear + MAX_CHILDBIRTH);
                                 Tools.SilentLogit("Constraint 12:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                                 individual.DidEstimate = true;
                              }
                           }
                           Tools.GetDates(MyIndividuals[MyFamilies[child.FamilyID].Wife].DeathDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
                           if (iYear != 0)
                           {
                              if (individual.MaxBirthYear > iYear)
                              {
                                 individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear);
                                 Tools.SilentLogit("Constraint 13:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                                 individual.DidEstimate = true;
                              }
                           }
                        }
                     }
                  }
                  else
                  {
                     child = null;
                  }

                  if (individual.MinBirthYear >= MIN_ALLOWED_YEAR)
                  {
                     if (individual.MinBirthYear > individual.MaxBirthYear)
                     {
                        individual.MaxBirthYear = individual.MinBirthYear;
                        Tools.SilentLogit("Min > Max:" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                        individual.DidEstimate = true;
                     }
                     if (individual.MinBirthYear > DateTime.Now.Year)
                     {
                        individual.MinBirthYear = DateTime.Now.Year;
                        Tools.SilentLogit("Min > Now:" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                        individual.DidEstimate = true;
                     }
                     if (individual.MaxBirthYear > DateTime.Now.Year)
                     {
                        individual.MaxBirthYear = DateTime.Now.Year;
                        Tools.SilentLogit("Max > Now:" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                        individual.DidEstimate = true;
                     }
                     if (individual.MinBirthYear == individual.MaxBirthYear)
                     {
                        individual.BirthDateText = individual.MinBirthYear.ToString() + " (calc)";
                        Tools.SilentLogit("Min = Max:" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                        individual.DidEstimate = true;
                     }
                     else
                     {
                        individual.BirthDateText = "between " + individual.MinBirthYear.ToString() + " and " + individual.MaxBirthYear.ToString() + " (calc)";
                        Tools.SilentLogit("Did Estimate:" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                        individual.DidEstimate = true;
                     }
                  }
               }
               if (individual.MinBirthYear < MIN_ALLOWED_YEAR)
               {
                  individual.MinBirthYear = MIN_ALLOWED_YEAR;
                  Tools.SilentLogit("Min < MIN_ALLOWED_YEAR:" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                  individual.DidEstimate = true;
               }
               if (individual.MaxBirthYear < 0)
               {
                  individual.MaxBirthYear = MIN_ALLOWED_YEAR;
                  Tools.SilentLogit("Max < MIN_ALLOWED_YEAR " + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
                  individual.DidEstimate = true;
               }

            } //
            Console.Write(".");
         } //
         Console.WriteLine("");

      }

      /// <summary>
      /// Summary of ExcludeLivingIndividuals.
      /// </summary>
      /// 		
      public void ExcludeLivingIndividuals()
      {
         // Individual theIndividual;
         DateTime dtActualDate = new DateTime();
         int iYear = 0;
         bool bIsAbout = false;
         int iEstimateStyle = 0;
         string sFamKey;
         int jCnt;
         int iCnt;
         Tools ugt = new Tools();
         int birthCutOff;

         birthCutOff = DateTime.Now.Year - m_cfg.BirthCutOffYears;

         FireStatusMessage("Excluding living individuals born after " + birthCutOff.ToString() + "....");
         for (iCnt = MyIndividuals.Count - 1; iCnt <= 0; iCnt--)
         {
            if (MyIndividuals[iCnt].BirthDateText.Length != 0)
            {

               Tools.GetDates(MyIndividuals[iCnt].BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);

               //if they were born after the cutoff and they are still living 
               //or their birth = 0 and we are doing date estimation....
               if ((iYear >= birthCutOff && MyIndividuals[iCnt].DeathDateText.Length == 0) || (iYear == 0 && m_cfg.DoDateEstimation == true))
               {
                  if (MyIndividuals[iCnt].FamList.Count > 0)
                  {
                     for (jCnt = 1; jCnt <= MyIndividuals[iCnt].FamList.Count; jCnt++)
                     {
                        if (MyIndividuals[iCnt].Sex == "F")
                        {
                           MyFamilies[MyIndividuals[iCnt].FamList[jCnt].FamId].Wife = "?";
                        }
                        else
                        {
                           MyFamilies[MyIndividuals[iCnt].FamList[jCnt].FamId].Husband = "?";
                        }
                     } //
                  }
                  sFamKey = MyIndividuals[iCnt].FamilyID + MyIndividuals[iCnt].ID;
                  try
                  {
                     MyChildren.Remove(sFamKey);
                  }
                  catch
                  {
                     //empty catch
                  }
                  try
                  {
                     MyIndividuals.Remove(iCnt);
                  }
                  catch
                  {
                     //empty catch
                  }
               }
            }

         } //

         //now eliminate families where both parents are unknown
         for (iCnt = MyFamilies.Count - 1; iCnt <= 0; iCnt--)
         {
            if (MyFamilies[iCnt].Wife == "?" && MyFamilies[iCnt].Husband == "?")
            {
               MyFamilies.Remove(iCnt);
            }
         } //

      }

      /// <summary>
      /// Summary of SaveEstimatedDatesList.
      /// </summary>
      /// 		
      public void SaveEstimatedDatesList()
      {
         FileStream fs1;
         StreamWriter sw1;
         string sFile;
         string estDateString;
         string tmgDateString;
         int numInList = 0;

         sFile = Tools.GetPath() + "\\EstimatedDates.txt";
         fs1 = new FileStream(sFile, FileMode.Create);
         sw1 = new StreamWriter(fs1);

         foreach (Individual theIndividual in MyIndividuals)
         {
            if (theIndividual.DidEstimate == true)
            {
               if (theIndividual.MinBirthYear != 0)
               {
                  if (theIndividual.MinBirthYear == theIndividual.MaxBirthYear)
                  {
                     estDateString = "EST " + theIndividual.MinBirthYear.ToString();
                     tmgDateString = "1" + theIndividual.MinBirthYear.ToString() + "0000010000000000";
                  }
                  else
                  {
                     estDateString = "BET " + theIndividual.MinBirthYear.ToString() + " AND " + theIndividual.MaxBirthYear.ToString();
                     tmgDateString = "1" + theIndividual.MinBirthYear.ToString() + "000005" + theIndividual.MaxBirthYear.ToString() + "000000";
                  }
                  sw1.WriteLine(theIndividual.ID + "," + theIndividual.Forenames + " /" + theIndividual.Surname + "/," + estDateString + "," + FixRin(theIndividual.ID));

                  numInList += 1;
               }
            }
         } //

         sw1.WriteLine(string.Format("List Total: {0}", numInList));

         sw1.Close();
         fs1.Close();
      }

      /// <summary>
      /// Summary of SetMinYear.
      /// </summary>
      /// <param name=oldMinYear></param>
      /// <param name=newMinYear></param>
      /// 		
      private int SetMinYear(int oldMinYear, int newMinYear)
      {
         if (newMinYear < oldMinYear)
         {
            return oldMinYear;
         }
         else
         {
            return newMinYear;
         }
      }

      /// <summary>
      /// Summary of SetMaxYear.
      /// </summary>
      /// <param name=oldMaxYear></param>
      /// <param name=newMaxYear></param>
      /// 		
      private int SetMaxYear(int oldMaxYear, int newMaxYear)
      {
         if (newMaxYear > oldMaxYear)
         {
            return oldMaxYear;
         }
         else
         {
            return newMaxYear;
         }
      }


      #endregion

   }

}
